Introduction

RNAseq data from:

Strenkert D, Schmollinger S, Gallaher SD, et al. Multiomics resolution of molecular events during a day in the life of Chlamydomonas. Proc Natl Acad Sci U S A. 2019;116(6):2374-2383.doi:10.1073/pnas.1815238116

Counts data normalisation and transformation with DESeq2

DESeq2:

Love MI, Huber W, Anders S (2014). “Moderated estimation of fold change and dispersion for RNA seq data with DESeq2.” Genome Biology, 15, 550. doi: 10.1186/s13059-014-0550-8

DESeq2 normalises the data according to library size (size factors) then uses a rlog transformation to diminish the impact of very low or very high expression genes on the subsequent analyses.

PCA of transformed counts data

PCA on rlog transformed count data.

PCA on rlog transformed count data.

PCA on rlog transformed count data.

PCA on rlog transformed count data.

On this Principal Component Analysis the cyclical nature of the experiment is apparent. From the time point 0h, the time points descend counter-clock wise, to return at the final 24h time point at the level of the first one. Note how time points at the end of the night (6h to 11h) are more closely related then the others, this is because Chlamydomonas cells are relatively quiescent at this part of their day cycle.

Hierarchical clustering of samples

Hierarchical clustering of rlog transformed count data.

Hierarchical clustering of rlog transformed count data.

The hierarchical clustering of the transformed data gives coherent clusters, grouping samples according to time periods. In this report I decided to use these clusters to separate the samples in the differential expression analysis.

Differential expression analysis with DESeq2

Here I use the previously defined clusters as formula to look for differentially expressed genes with DESeq2. However this can also be achieved by using directly the time conditions (as the R script in the workflow does).

## [1] "Total DEG in at least one time transition: 85.614094148011 %"

The use of time condition (as in the workflow R script) instead of the clusters gives less DEG, about 70%.

Rhythm analysis with DiscoRhythm

DiscoRhythm:

Matthew Carlucci, Algimantas Kriščiūnas, Haohan Li, Povilas Gibas, Karolis Koncevičius, Art Petronis, Gabriel Oh, DiscoRhythm: an easy-to-use web application and R package for discovering rhythmicity, Bioinformatics, Volume 36, Issue 6, 15 March 2020, Pages 1952–1954, https://doi.org/10.1093/bioinformatics/btz834

##       0                         2                        
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       4                         6                        
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       8                         10                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       10.5                      11                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       11.5                      12                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       14                        16                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       18                        20                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"
##       22                        24                       
## Total "3"                       "3"                      
##       "Biological Sample 1 (1)" "Biological Sample 1 (1)"
##       "Biological Sample 2 (1)" "Biological Sample 2 (1)"
##       "Biological Sample 3 (1)" "Biological Sample 3 (1)"

The Lomb-Scargle qvalue distribution has a problematic profile, we will focus on Cosinor.

The acrophase is the time when the expression of the gene peaks. We will focus on the acrophase parameter instead of the amplitude of the expression signal to find putative regulators. Indeed, what we are interested in is not the intensity of gene expression, but rather the timing of expression.

Annotation

General view of rhythmic genes acrophases

Acrophases distribution.

Acrophases distribution.

c(paste0("Chloroplast", " (", nrow(final_data[final_data$simplified_subcellular_location == "Chloroplast",]), ")"),
  paste0("Chromosome", " (", nrow(final_data[final_data$simplified_subcellular_location == "Chromosome",]), ")"),
  paste0("Cilium", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cilium",]), ")"),
  paste0("Cytoplasm", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cytoplasm",]), ")"),
  paste0("Cytoskeleton", " (", nrow(final_data[final_data$simplified_subcellular_location == "Cytoskeleton",]), ")"),
  paste0("Endoplasmic reticulum", " (", nrow(final_data[final_data$simplified_subcellular_location == "Endoplasmic reticulum",]), ")"),
  paste0("Golgi apparatus", " (", nrow(final_data[final_data$simplified_subcellular_location == "Golgi apparatus",]), ")"),   
  paste0("Membrane", " (", nrow(final_data[final_data$simplified_subcellular_location == "Membrane",]), ")"),
  paste0("Mitochondrion", " (", nrow(final_data[final_data$simplified_subcellular_location == "Mitochondrion",]), ")"),
  paste0("Nucleus", " (", nrow(final_data[final_data$simplified_subcellular_location == "Nucleus",]), ")"),
  paste0("Other", " (", nrow(final_data[final_data$simplified_subcellular_location == "Other",]), ")"),
  paste0("unknown", " (", nrow(final_data[final_data$simplified_subcellular_location == "unknown",]), ")")) -> locations
   
#final_data2 <- filter(final_data, simplified_subcellular_location != "unknown")

ggplot(data = final_data, mapping = aes(x=CS.acrophase, fill=simplified_subcellular_location))+
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =0, ymax = Inf, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =0, ymax = Inf, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =0, ymax = Inf, alpha =0.3)+
    geom_histogram(aes(x = CS.acrophase, y = ..density..), binwidth = 0.3) +
    geom_line(stat = "density", alpha=0.5) +
    facet_wrap(~simplified_subcellular_location)+
    labs( x = "Acrophase", y = "Genes",
            title ="Acrophases distribution according to cellular location",
            subtitle = "Cosinor method")+
    scale_fill_discrete(name = "Cellular location", labels = locations)
Acrophases distribution.

Acrophases distribution.

Putative and known regulators

# Recovering some rhythmic OTAFs
opr <- final_data[ which(startsWith(final_data$gene_description, "OctotricoPeptide Repeat")) , ]                                                           
ppr <- final_data[ which(startsWith(final_data$gene_description, "PentatricoPeptide Repeat")) , ]
tpr <- final_data[ which(startsWith(final_data$gene_description, "TetratricoPeptide Repeat")) , ]

otaf <- union_all(opr, ppr)
otaf <- union_all(otaf, tpr)

# Adding expression data:
columns <- colnames(otaf)
otaf <- left_join(otaf, rlog_df)
colnames(otaf) <- make.unique(c(columns, rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)))

# Predicted chloroplast imported OTAFs
multi_otaf_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast"),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    multi_otaf_chloro <- rbind(multi_otaf_chloro, tmp_df)
}

multi_otaf_chloro <- multi_otaf_chloro[-1,]

# Predicted mitochondrion imported OTAFs
multi_otaf_mito <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Mitochondrion"),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    multi_otaf_mito <- rbind(multi_otaf_mito, tmp_df)
}

multi_otaf_mito <- multi_otaf_mito[-1,]
Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

Gene expression models.

To pair OTAFs and their putative organellar mRNA targets we must look at:

acro_morning_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in chloro[which(chloro$CS.acrophase <16 & chloro$CS.acrophase >12 ),]$gene_symbol) {
    chloro[chloro$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
        tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
        tmp_df$gene <- prot
        acro_morning_chloro <- rbind(acro_morning_chloro, tmp_df)
}

acro_morning_chloro <- acro_morning_chloro[-1,]


otaf_chloro_acro_dawn <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <12 & otaf$CS.acrophase >8),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    otaf_chloro_acro_dawn <- rbind(otaf_chloro_acro_dawn, tmp_df)
}

otaf_chloro_acro_dawn <- otaf_chloro_acro_dawn[-1,]


# Plots 

ggplot(data = otaf_chloro_acro_dawn, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) + 
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 13, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 13, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 13, alpha =0.3)+
    facet_wrap(~gene) +
    ylim(4, 13) +
    geom_smooth(method = "lm", se = FALSE, level = 0.95,
                formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
                fullrange = TRUE) +
    theme(legend.position = "none") +
    geom_point() +
    labs(y = "rlog(counts)", x = "Time (h)",
         title ="Chloroplast located OTAFs, acrophase at dawn",
         subtitle = "Cosinor method") +
    theme(plot.title = element_text(size = 11))+
    theme(strip.text.x = element_text(size = 11))
Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Here, we can identify known OTAF/chloroplast mRNA pairs/trios:

But also other potential OTAF/mRNA pairs!

acro_afternoon_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in chloro[which(chloro$CS.acrophase <20 & chloro$CS.acrophase >16 ),]$gene_symbol) {
    chloro[chloro$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
        tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
        tmp_df$gene <- prot
        acro_afternoon_chloro <- rbind(acro_afternoon_chloro, tmp_df)
}

acro_afternoon_chloro <- acro_afternoon_chloro[-1,]


otaf_chloro_acro_day <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <16 & otaf$CS.acrophase >12),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    otaf_chloro_acro_day <- rbind(otaf_chloro_acro_day, tmp_df)
}

otaf_chloro_acro_day <- otaf_chloro_acro_day[-1,]


# Plots 

ggplot(data = otaf_chloro_acro_day, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) + 
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 11, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 11, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 11, alpha =0.3)+
    facet_wrap(~gene) +
    ylim(4, 11) +
    geom_smooth(method = "lm", se = FALSE, level = 0.95,
                formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
                fullrange = TRUE) +
    theme(legend.position = "none") +
    geom_point() +
    labs(y = "rlog(counts)", x = "Time (h)",
         title ="Chloroplast located OTAFs, acrophase at dawn",
         subtitle = "Cosinor method") +
    theme(plot.title = element_text(size = 11))+
    theme(strip.text.x = element_text(size = 11))
Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Here, we can identify known OTAF/chloroplast mRNA pairs:

And other potential OTAF/mRNA pairs…

acro_evening_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in chloro[which(chloro$CS.acrophase <24 & chloro$CS.acrophase >20 ),]$gene_symbol) {
    chloro[chloro$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
        tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
        tmp_df$gene <- prot
        acro_evening_chloro <- rbind(acro_evening_chloro, tmp_df)
}

acro_evening_chloro <- acro_evening_chloro[-1,]


otaf_chloro_acro_afternoon <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <20 & otaf$CS.acrophase >16),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    otaf_chloro_acro_afternoon <- rbind(otaf_chloro_acro_afternoon, tmp_df)
}

otaf_chloro_acro_afternoon <- otaf_chloro_acro_afternoon[-1,]


# Plots 

ggplot(data = otaf_chloro_acro_afternoon, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) + 
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 11, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 11, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 11, alpha =0.3)+
    facet_wrap(~gene) +
    ylim(4, 11) +
    geom_smooth(method = "lm", se = FALSE, level = 0.95,
                formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
                fullrange = TRUE) +
    theme(legend.position = "none") +
    geom_point() +
    labs(y = "rlog(counts)", x = "Time (h)",
         title ="Chloroplast located OTAFs, acrophase at day",
         subtitle = "Cosinor method") +
    theme(plot.title = element_text(size = 11))+
    theme(strip.text.x = element_text(size = 11))
Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

## [1] "No chloroplast gene with max expression at dusk."
acro_night_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in chloro[which(chloro$CS.acrophase <4 & chloro$CS.acrophase >0 ),]$gene_symbol) {
    chloro[chloro$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
        tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
        tmp_df$gene <- prot
        acro_night_chloro <- rbind(acro_night_chloro, tmp_df)
}

acro_night_chloro <- acro_night_chloro[-1,]


otaf_chloro_acro_dusk <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <24 & otaf$CS.acrophase >20),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    otaf_chloro_acro_dusk <- rbind(otaf_chloro_acro_dusk, tmp_df)
}

otaf_chloro_acro_dusk <- otaf_chloro_acro_dusk[-1,]


# Plots 

ggplot(data = otaf_chloro_acro_dusk, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) + 
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 8, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 8, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 8, alpha =0.3)+
    facet_wrap(~gene) +
    ylim(4, 8) +
    geom_smooth(method = "lm", se = FALSE, level = 0.95,
                formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
                fullrange = TRUE) +
    theme(legend.position = "none") +
    geom_point() +
    labs(y = "rlog(counts)", x = "Time (h)",
         title ="Chloroplast located OTAFs, acrophase at dusk",
         subtitle = "Cosinor method") +
    theme(plot.title = element_text(size = 11))+
    theme(strip.text.x = element_text(size = 11))
Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

acro_night_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in chloro[which(chloro$CS.acrophase <8 & chloro$CS.acrophase >4 ),]$gene_symbol) {
    chloro[chloro$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
        tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
        tmp_df$gene <- prot
        acro_night_chloro <- rbind(acro_night_chloro, tmp_df)
}

acro_night_chloro <- acro_night_chloro[-1,]


otaf_chloro_acro_night <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <4 & otaf$CS.acrophase >0),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    otaf_chloro_acro_night <- rbind(otaf_chloro_acro_night, tmp_df)
}

otaf_chloro_acro_night <- otaf_chloro_acro_night[-1,]


# Plots 

ggplot(data = otaf_chloro_acro_night, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) + 
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 9, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 9, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 9, alpha =0.3)+
    facet_wrap(~gene) +
    ylim(4, 9) +
    geom_smooth(method = "lm", se = FALSE, level = 0.95,
                formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
                fullrange = TRUE) +
    theme(legend.position = "none") +
    geom_point() +
    labs(y = "rlog(counts)", x = "Time (h)",
         title ="Chloroplast located OTAFs, acrophase in early night",
         subtitle = "Cosinor method") +
    theme(plot.title = element_text(size = 11))+
    theme(strip.text.x = element_text(size = 11))
Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

acro_night_chloro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in chloro[which(chloro$CS.acrophase <12 & chloro$CS.acrophase >8 ),]$gene_symbol) {
    chloro[chloro$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
        tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
        tmp_df$gene <- prot
        acro_night_chloro <- rbind(acro_night_chloro, tmp_df)
}

acro_night_chloro <- acro_night_chloro[-1,]


otaf_chloro_acro_night <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Chloroplast" & otaf$CS.acrophase <8 & otaf$CS.acrophase >4),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    otaf_chloro_acro_night <- rbind(otaf_chloro_acro_night, tmp_df)
}

otaf_chloro_acro_night <- otaf_chloro_acro_night[-1,]


# Plots 

ggplot(data = otaf_chloro_acro_night, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) + 
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 13, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 13, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 13, alpha =0.3)+
    facet_wrap(~gene) +
    ylim(4, 13) +
    geom_smooth(method = "lm", se = FALSE, level = 0.95,
                formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
                fullrange = TRUE) +
    theme(legend.position = "none") +
    geom_point() +
    labs(y = "rlog(counts)", x = "Time (h)",
         title ="Chloroplast located OTAFs, acrophase at end of night",
         subtitle = "Cosinor method") +
    theme(plot.title = element_text(size = 11))+
    theme(strip.text.x = element_text(size = 11))
Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Here, we can identify a known OTAF/chloroplast mRNA pair: MRL1 and rbcL

And other potential OTAF/mRNA pairs…?

acro_mito <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in mito$gene_symbol) {
    mito[mito$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
        tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
        tmp_df$gene <- prot
        acro_mito <- rbind(acro_mito, tmp_df)
}

acro_mito <- acro_mito[-1,]


otaf_mito_acro <- data.frame(time=0, gene_expression=0.0, gene="")

for (prot in otaf[which(otaf$subcellular_location == "Mitochondrion"),]$gene_symbol){
    otaf[otaf$gene_symbol == prot, 19:66] %>%
        pivot_longer(cols = c(1:48), names_to = "time", values_to = "gene_expression") -> tmp_df
    tmp_df$time <- rep(c(0, 2, 4, 6, 8, 10, 10.5, 11, 11.5, 12, 14, 16, 18, 20, 22, 24), each=3)
    tmp_df$gene <- prot
    otaf_mito_acro <- rbind(otaf_mito_acro, tmp_df)
}

otaf_mito_acro <- otaf_mito_acro[-1,]


# Plots 

ggplot(data = otaf_mito_acro, mapping = aes(x=time, y=gene_expression, group=gene, color=gene)) + 
    annotate("rect", fill = "darkgray", xmin = 0, xmax = 11, ymin =4, ymax = 13, alpha =0.3) +
    annotate("rect", fill = "gold", xmin = 11, xmax = 23, ymin =4, ymax = 13, alpha =0.3) +
    annotate("rect", fill = "darkgray", xmin = 23, xmax = Inf, ymin =4, ymax = 13, alpha =0.3)+
    facet_wrap(~gene) +
    ylim(4, 13) +
    geom_smooth(method = "lm", se = FALSE, level = 0.95,
                formula = y ~ sin(x / periode * 2 * pi) + cos(x / periode * 2 * pi),
                fullrange = TRUE) +
    theme(legend.position = "none") +
    geom_point() +
    labs(y = "rlog(counts)", x = "Time (h)",
         title ="Mitochondrion located OTAFs,",
         subtitle = "Cosinor method") +
    theme(plot.title = element_text(size = 11))+
    theme(strip.text.x = element_text(size = 11))
Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Candidate OTAF/mRNA target pairs.

Rhythmic NCL mRNA expression.

Rhythmic NCL mRNA expression.

References

Eberhard S, Loiselay C, Drapier D, Bujaldon S, Girard-Bascou J, Kuras R, Choquet Y, Wollman FA. Dual functions of the nucleus-encoded factor TDA1 in trapping and translation activation of atpA transcripts in Chlamydomonas reinhardtii chloroplasts. Plant J. 2011 Sep;67(6):1055-66. doi: 10.1111/j.1365-313X.2011.04657.x. Epub 2011 Jul 18. PMID: 21623973.

Wang F, Johnson X, Cavaiuolo M, Bohne AV, Nickelsen J, Vallon O. Two Chlamydomonas OPR proteins stabilize chloroplast mRNAs encoding small subunits of photosystem II and cytochrome b6 f. Plant J. 2015 Jun;82(5):861-73. doi: 10.1111/tpj.12858. PMID: 25898982.

Cline, S. G., Laughbaum, I. A. and Hamel, P. P. (2017) CCS2, an Octatricopeptide-Repeat Protein, Is Required for Plastid Cytochrome c Assembly in the Green Alga Chlamydomonas reinhardtii. Frontiers in plant science, 8, 1306. https://doi.org/10.3389/fpls.2017.01306

Viola S, Cavaiuolo M, Drapier D, et al. MDA1, a nucleus-encoded factor involved in the stabilization and processing of the atpA transcript in the chloroplast of Chlamydomonas. The Plant Journal: for Cell and Molecular Biology. 2019 Jun;98(6):1033-1047. DOI: 10.1111/tpj.14300.

Shin-Ichiro Ozawa, Marina Cavaiuolo, Domitille Jarrige, Richard Kuras, Mark Rutgers, Stephan Eberhard, Dominique Drapier, Francis-André Wollman, Yves Choquet, The OPR Protein MTHI1 Controls the Expression of Two Different Subunits of ATP Synthase CFo in Chlamydomonas reinhardtii, The Plant Cell, Volume 32, Issue 4, April 2020, Pages 1179–1203, https://doi.org/10.1105/tpc.19.00770

## R version 4.0.3 (2020-10-10)
## Platform: x86_64-conda-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS/LAPACK: /shared/ifbstor1/software/miniconda/envs/r-4.0.3/lib/libopenblasp-r0.3.10.so
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] parallel  stats4    stats     graphics  grDevices utils     datasets 
## [8] methods   base     
## 
## other attached packages:
##  [1] gprofiler2_0.2.1            DiscoRhythm_1.6.0          
##  [3] pheatmap_1.0.12             ClassDiscovery_3.4.0       
##  [5] oompaBase_3.2.9             cluster_2.1.1              
##  [7] DESeq2_1.30.1               SummarizedExperiment_1.20.0
##  [9] Biobase_2.50.0              GenomicRanges_1.42.0       
## [11] GenomeInfoDb_1.26.7         IRanges_2.24.1             
## [13] S4Vectors_0.28.1            BiocGenerics_0.36.1        
## [15] MatrixGenerics_1.2.1        matrixStats_0.60.1         
## [17] data.table_1.14.0           forcats_0.5.1              
## [19] stringr_1.4.0               dplyr_1.0.7                
## [21] purrr_0.3.4                 readr_2.0.1                
## [23] tidyr_1.1.3                 tibble_3.1.4               
## [25] tidyverse_1.3.1             knitr_1.33                 
## [27] factoextra_1.0.7            ggplot2_3.3.5              
## [29] FactoMineR_2.4             
## 
## loaded via a namespace (and not attached):
##   [1] utf8_1.2.2             shinydashboard_0.7.1   tidyselect_1.1.1      
##   [4] heatmaply_1.2.1        RSQLite_2.2.8          AnnotationDbi_1.52.0  
##   [7] htmlwidgets_1.5.4      grid_4.0.3             TSP_1.1-10            
##  [10] BiocParallel_1.24.1    munsell_0.5.0          codetools_0.2-18      
##  [13] DT_0.18                miniUI_0.1.1.1         withr_2.4.2           
##  [16] colorspace_2.0-2       highr_0.9              gnm_1.1-1             
##  [19] rstudioapi_0.13        leaps_3.1              oompaData_3.1.1       
##  [22] ggsignif_0.6.2         labeling_0.4.2         GenomeInfoDbData_1.2.4
##  [25] farver_2.1.0           bit64_4.0.5            vctrs_0.3.8           
##  [28] generics_0.1.0         lambda.r_1.2.4         xfun_0.25             
##  [31] R6_2.5.1               seriation_1.3.0        locfit_1.5-9.4        
##  [34] bitops_1.0-7           cachem_1.0.6           DelayedArray_0.16.3   
##  [37] assertthat_0.2.1       promises_1.2.0.1       shinycssloaders_1.0.0 
##  [40] scales_1.1.1           nnet_7.3-15            ggExtra_0.9           
##  [43] gtable_0.3.0           MetaCycle_1.2.0        rlang_0.4.11          
##  [46] genefilter_1.72.1      systemfonts_1.0.2      scatterplot3d_0.3-41  
##  [49] splines_4.0.3          rstatix_0.7.0          lazyeval_0.2.2        
##  [52] shinyBS_0.61           broom_0.7.9            abind_1.4-5           
##  [55] BiocManager_1.30.16    yaml_2.2.1             reshape2_1.4.4        
##  [58] modelr_0.1.8           backports_1.2.1        httpuv_1.6.2          
##  [61] tools_4.0.3            ellipsis_0.3.2         kableExtra_1.3.4      
##  [64] jquerylib_0.1.4        RColorBrewer_1.1-2     Rcpp_1.0.7            
##  [67] plyr_1.8.6             zlibbioc_1.36.0        RCurl_1.98-1.4        
##  [70] ggpubr_0.4.0           viridis_0.6.1          haven_2.4.3           
##  [73] ggrepel_0.9.1          fs_1.5.0               magrittr_2.0.1        
##  [76] futile.options_1.0.1   magick_2.7.2           openxlsx_4.2.4        
##  [79] reprex_2.0.1           hms_1.1.0              shinyjs_2.0.0         
##  [82] mime_0.11              evaluate_0.14          xtable_1.8-4          
##  [85] XML_3.99-0.7           VennDiagram_1.6.20     rio_0.5.27            
##  [88] mclust_5.4.7           readxl_1.3.1           gridExtra_2.3         
##  [91] compiler_4.0.3         crayon_1.4.1           htmltools_0.5.2       
##  [94] mgcv_1.8-34            later_1.3.0            tzdb_0.1.2            
##  [97] geneplotter_1.68.0     lubridate_1.7.10       DBI_1.1.1             
## [100] formatR_1.11           dbplyr_2.1.1           MASS_7.3-53.1         
## [103] relimp_1.0-5           BiocStyle_2.18.1       Matrix_1.3-4          
## [106] car_3.0-11             cli_3.0.1              pkgconfig_2.0.3       
## [109] flashClust_1.01-2      registry_0.5-1         foreign_0.8-81        
## [112] plotly_4.9.4.1         xml2_1.3.2             foreach_1.5.1         
## [115] svglite_2.0.0          annotate_1.68.0        bslib_0.2.5.1         
## [118] webshot_0.5.2          XVector_0.30.0         rvest_1.0.1           
## [121] digest_0.6.27          rmarkdown_2.10         cellranger_1.1.0      
## [124] dendextend_1.15.1      curl_4.3.2             shiny_1.6.0           
## [127] nlme_3.1-152           lifecycle_1.0.0        jsonlite_1.7.2        
## [130] carData_3.0-4          futile.logger_1.4.3    qvcalc_1.0.2          
## [133] viridisLite_0.4.0      fansi_0.5.0            pillar_1.6.2          
## [136] lattice_0.20-41        fastmap_1.1.0          httr_1.4.2            
## [139] survival_3.2-10        glue_1.4.2             zip_2.2.0             
## [142] UpSetR_1.4.0           iterators_1.0.13       bit_4.0.4             
## [145] stringi_1.7.3          sass_0.4.0             blob_1.2.2            
## [148] memoise_2.0.0
LS0tCnRpdGxlOiAicmh5dGhtaWNfYW5hbHlzZXMuUm1kIgphdXRob3I6ICJEb21pdGlsbGUgSmFycmlnZSIKZGF0ZTogJ2ByIFN5cy5EYXRlKClgJwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAgdGhlbWU6IHlldGkKICAgIHRvYzogeWVzCiAgICBjb2RlX2ZvbGRpbmc6ICJoaWRlIgogIHBkZl9kb2N1bWVudDoKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFLCBldmFsPVRSVUV9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGV2YWwgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUpCgpvcHRpb25zKHNjaXBlbiA9IDEyKSAjIyBNYXggbnVtYmVyIG9mIGRpZ2l0cyBmb3Igbm9uLXNjaWVudGlmaWMgbm90YXRpb24KYGBgCgpgYGB7ciB3b3JraW5nX2RpciwgaW5jbHVkZT1GQUxTRX0Kc2V0d2QoIi9zaGFyZWQvaWZic3RvcjEvcHJvamVjdHMvZHViaWkyMDIxL2RqYXJyaWdlL3Byb2pldF9zY2llbnRpZmlxdWUvc2NyaXB0cyIpCmBgYAoKYGBge3IgbGlicmFyaWVzLCBpbmNsdWRlPUZBTFNFfQpyZXF1aXJlZF9saWIgPC0gYygiRmFjdG9NaW5lUiIsCiAgICAgICAgICAgICAgICAgICJmYWN0b2V4dHJhIiwKICAgICAgICAgICAgICAgICAgImtuaXRyIiwKICAgICAgICAgICAgICAgICAgInRpZHl2ZXJzZSIsCiAgICAgICAgICAgICAgICAgICJkYXRhLnRhYmxlIiwKICAgICAgICAgICAgICAgICAgIlN1bW1hcml6ZWRFeHBlcmltZW50IiwKICAgICAgICAgICAgICAgICAgInRpYmJsZSIsCiAgICAgICAgICAgICAgICAgICJERVNlcTIiLAogICAgICAgICAgICAgICAgICAiZHBseXIiLAogICAgICAgICAgICAgICAgICAiQ2xhc3NEaXNjb3ZlcnkiLAogICAgICAgICAgICAgICAgICAicGhlYXRtYXAiKQoKcmVxdWlyZWRfYmlvYyA8LSBjKCJEaXNjb1JoeXRobSIsCiAgICAgICAgICAgICAgICAgICAiZ3Byb2ZpbGVyMiIpCgojIyMgQ1JBTiBsaWJyYXJpZXMgCmZvciAobGliIGluIHJlcXVpcmVkX2xpYikgewogICAgaWYgKCFyZXF1aXJlKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgewogICAgICAgIGluc3RhbGwucGFja2FnZXMobGliKQogICAgfQogICAgcmVxdWlyZShsaWIsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKfQoKCiMjIyBCaW9jbWFuYWdlciBsaWJyYXJpZXMgCgppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseT1UUlVFKSkKICAgIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKCmZvciAobGliIGluIHJlcXVpcmVkX2Jpb2MpewogICAgaWYgKCFyZXF1aXJlKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgewogICAgICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKGxpYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQogICAgfQogICAgcmVxdWlyZShsaWIsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKfQoKCmBgYAoKIyMgSW50cm9kdWN0aW9uCgojIyMjIFJOQXNlcSBkYXRhIGZyb206CgoqKlN0cmVua2VydCBELCBTY2htb2xsaW5nZXIgUywgR2FsbGFoZXIgU0QsIGV0IGFsLiBNdWx0aW9taWNzIHJlc29sdXRpb24gb2YgbW9sZWN1bGFyIGV2ZW50cyBkdXJpbmcgYSBkYXkgaW4gdGhlIGxpZmUgb2YgQ2hsYW15ZG9tb25hcy4gUHJvYyBOYXRsIEFjYWQgU2NpIFUgUyBBLiAyMDE5OzExNig2KToyMzc0LTIzODMuW2RvaToxMC4xMDczL3BuYXMuMTgxNTIzODExNl0oaHR0cHM6Ly93d3cucG5hcy5vcmcvY29udGVudC8xMTYvNi8yMzc0KSoqCgoKIyMjIyBGbG93IGNoYXJ0IG9mIG15IHByb2plY3QgUk5Bc2VxIGFuYWx5c2lzIHBhcnQ6CiFbbXkgUk5Bc2VxIHdvcmtmbG93XShmbG93X2NoYXJ0X1JOQV9naXRodWJfdmVyLnBuZykKCgpBZnRlciB0cmVhdGluZyB0aGUgcmF3IFJOQXNlcSBkYXRhIHdpdGggbXkgYHJuYV93b3JrZmxvdy5zbWtgLCBJIG9idGFpbmVkIGEgY291bnRzIHRhYmxlIHdpdGggZWFjaCBSTkFzZXEgbGlicmFyeSwgZm9sbG93aW5nIHRoZSB0aW1lIHNlcmllcyBvcmRlci4KCkluIHRoaXMgUiBtYXJrZG93biByZXBvcnQsIEkgIHBlcmZvcm0gYSBzaG9ydCBhbmFseXNpcyBvZiB0aGlzIGRhdGEgYW5kIGV4dHJhY3QgaW5mb3JtYXRpb24gb24gc29tZSBwb3RlbnRpYWwgb3Iga25vd24gT3JnYW5lbGxhciBUcmFucy1BY3RpbmcgRmFjdG9ycyAoT1RBRnMpIG9mIF9DaGxhbXlkb21vbmFzIHJlaW5oYXJkdGlpXy4KCmBgYHtyIGRhdGFfbG9hZGluZ19hbmRfcHJlcGFyYXRpb259CgojIyBMb2FkaW5nIGNvdW50cyBkYXRhIGFuZCBtZXRhZGF0YQptZXRhX3RlbXAgPC0gcmVhZC5jc3YoIi4uL2RhdGEvc2FtcGxlX0Rpc2NvUnl0aG1fZm9ybWF0LnRzdiIsIHNlcD0iXHQiKQpjb3VudHNfcnVuZF9kZiA8LSByZWFkLmNzdigiLi4vcmVzdWx0cy9tYXBwaW5nL2Z1bGxfZGF0YS90b3RhbF9jb3VudHNfaW50LmNzdiIsIHNlcD0iXHQiLCByb3cubmFtZXMgPSAxKQoKIyMgUGlja2luZyBjb2xvcnMgZm9yIHRpbWVwb2ludHMKbWV0YV90ZW1wJGNvbG9yIDwtIGMocmVwKCIjMDAwZjNiIiwgMyksIHJlcCgiIzAwMTQ0ZSIsIDMpLCByZXAoIiMwMDE5NjIiLCAzKSwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCIjMDAxMTYyIiwgMyksIHJlcCgiIzAwMTc4OSIsIDMpLCByZXAoIiMwMDFlYjEiLCAzKSwKICAgICAgICAgICAgICAgICAgICByZXAoIiMxNDNiZmYiLCAzKSwgcmVwKCIjODZiY2Y5IiwgMyksIHJlcCgiI2ZmYzU3NiIsIDMpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIiNmZmQ0MDAiLCAzKSwgcmVwKCIjZmZlOTAwIiwgMyksIHJlcCgiI2ZmZjA0ZSIsIDMpLAogICAgICAgICAgICAgICAgICAgIHJlcCgiI2ZmZjU4OSIsIDMpLCByZXAoIiNjZWMwMzEiLCAzKSwgcmVwKCIjZmZiZjAwIiwgMyksCiAgICAgICAgICAgICAgICAgICAgcmVwKCIjMDAxMTYyIiwgMykpCgojIyBMb2FkaW5nIGFubm90YXRpb24gZGF0YQphbm5vdGF0aW9ucyA8LSByZWFkLmNzdigiLi4vZGF0YS9waHl0b3pvbWUvQ3JlaW5oYXJkdGlpL3Y1LjYvYW5ub3RhdGlvbi9nZW5lX2Fubm90YXRpb24udHN2IiwKICAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJcdCIpCmFubm90YXRpb25zX29yZ2FuZWxsZXMgPC0gcmVhZC5jc3YoIi4uL2RhdGEvcGh5dG96b21lL0NyZWluaGFyZHRpaS92NS42L2Fubm90YXRpb24vb3JnYW5lbGxlc19hbm5vdGF0aW9uLnRzdiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJcdCIpCgojIC8hXCBSZW1vdmluZyBkdXBsaWNhdGVkIGdlbmVzCmFubm90YXRpb25zJGdlbmVfaWQgIDwtIG1ha2UudW5pcXVlKGFubm90YXRpb25zJGdlbmVfaWQsIHNlcD0iLiIpCgoKIyMgTWF0cml4IGNvbnZlcnNpb24KbWF0cml4X2NvdW50c19ERVNlcTIgPC0gYXMubWF0cml4KGNvdW50c19ydW5kX2RmWywyOjQ5XSkgCnJvd25hbWVzKG1hdHJpeF9jb3VudHNfREVTZXEyKSA8LSBjb3VudHNfcnVuZF9kZlssMV0KCmBgYAoKIyMgQ291bnRzIGRhdGEgbm9ybWFsaXNhdGlvbiBhbmQgdHJhbnNmb3JtYXRpb24gd2l0aCBERVNlcTIKCioqREVTZXEyOioqIAoKTG92ZSBNSSwgSHViZXIgVywgQW5kZXJzIFMgKDIwMTQpLiAiTW9kZXJhdGVkIGVzdGltYXRpb24gb2YgZm9sZCBjaGFuZ2UgYW5kIGRpc3BlcnNpb24gZm9yIFJOQSBzZXEgZGF0YSB3aXRoIERFU2VxMi4iIF9HZW5vbWUgQmlvbG9neV8sIDE1LCA1NTAuIGRvaTogMTAuMTE4Ni9zMTMwNTktMDE0LTA1NTAtOAoKYGBge3IgZGF0YV9ub3JtYWxpc2F0aW9uX3dpdGhfREVTZXEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjIyBOb3JtYWxpc2F0aW9uIGFuZCB0cmFuc2Zvcm1hdGlvbiBvZiBjb3VudCBkYXRhIHdpdGggREVTZXEyICMjIyMKZGRzRnVsbCA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IG1hdHJpeF9jb3VudHNfREVTZXEyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBtZXRhX3RlbXAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiB0aW1lKQoKIyMgU2l6ZSBmYWN0b3JzCmRkc0Z1bGwgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhkZHNGdWxsKQoKIyMgVGFraW5nIG91dCB1bmV4cHJlc3NlZCBnZW5lcwpkZHNGdWxsIDwtIGRkc0Z1bGxbIHJvd1N1bXMoY291bnRzKGRkc0Z1bGwpKSA+IDAsIF0KCiMjIHJsb2cgdHJhbnNmb3JtYXRpb24KcmxvZ19kYXRhIDwtIHJsb2coZGRzRnVsbCwgYmxpbmQ9VFJVRSkKYm94cGxvdChjb3VudHMoZGRzRnVsbCwgbm9ybWFsaXplZD1GQUxTRSksCiAgICAgICAgY29sID0gbWV0YV90ZW1wJGNvbG9yLAogICAgICAgIGhvcml6b250YWwgPSBUUlVFLCAKICAgICAgICBsYXMgPSAxLAogICAgICAgIGNleC5heGlzID0gMC40NSwKICAgICAgICBjZXggPSAwLjUsCiAgICAgICAgeGxhYiA9ICJyYXcgdmFsdWUiLAogICAgICAgIG1haW49IkJveHBsb3RzIG9mIHVudHJhbnNmb3JtZWQgCmdlbmUgY291bnRzIikKCmJveHBsb3QoYXNzYXkocmxvZ19kYXRhKSwKICAgICAgICBjb2wgPSBtZXRhX3RlbXAkY29sb3IsCiAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUsIAogICAgICAgIGxhcyA9IDEsCiAgICAgICAgY2V4LmF4aXMgPSAwLjQ1LAogICAgICAgIGNleCA9IDAuNSwKICAgICAgICB4bGFiID0gInJsb2codmFsdWUpIiwKICAgICAgICBtYWluPSJCb3hwbG90cyBvZiBybG9nIHRyYW5zZm9ybWVkIApnZW5lIGNvdW50cyIpCgoKIyMgVHJhbnNmb3JtYXRpb24gdmlzdWFsaXNhdGlvbgpwYXIobWZyb3c9YygxLDIpKQpwbG90KGNvdW50cyhkZHNGdWxsLCBub3JtYWxpemVkPUZBTFNFKVssMTE6MTJdLApwY2g9MTYsIGNleD0wLjMsIHhsaW09YygwLDIwZTMpLCB5bGltPWMoMCwyMGUzKSwgbWFpbj0icmF3IGNvdW50cyIpCgpwbG90KGFzc2F5KHJsb2dfZGF0YSlbLDExOjEyXSwKcGNoPTE2LCBjZXg9MC4zLCBtYWluPSJybG9nIG5vcm1hbGl6ZWQgY291bnRzIikKcGFyKG1mcm93PWMoMSwxKSkKCmBgYAoKREVTZXEyIG5vcm1hbGlzZXMgdGhlIGRhdGEgYWNjb3JkaW5nIHRvIGxpYnJhcnkgc2l6ZSAoc2l6ZSBmYWN0b3JzKSB0aGVuIHVzZXMgYSBybG9nIHRyYW5zZm9ybWF0aW9uIHRvIGRpbWluaXNoIHRoZSBpbXBhY3Qgb2YgdmVyeSBsb3cgb3IgdmVyeSBoaWdoIGV4cHJlc3Npb24gZ2VuZXMgb24gdGhlIHN1YnNlcXVlbnQgYW5hbHlzZXMuIAoKIyMgUENBIG9mIHRyYW5zZm9ybWVkIGNvdW50cyBkYXRhCgpgYGB7ciBQQ0FfcmxvZ19kYXRhLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD02LCBvdXQud2lkdGg9IjkwJSIsIGZpZy5jYXA9IlBDQSBvbiBybG9nIHRyYW5zZm9ybWVkIGNvdW50IGRhdGEuIn0KIyMgcmxvZyB0cmFuc2Zvcm1lZCBkYXRhLCBQQ0EKCiMjIGV4dHJhY3QgcmxvZyBtYXRyaXgKY291bnRzX3Jsb2cgPC0gYXNzYXkocmxvZ19kYXRhKQoKIyMgUnVuIFBDQQpyZXNfcGNhIDwtIFBDQSh0KGNvdW50c19ybG9nKSwgZ3JhcGg9RkFMU0UpCgojIyBHcmFwaHMKZnZpel9laWcocmVzX3BjYSwgdGl0bGU9IlBDQSBvZiBybG9nIGRhdGEsIEVpZ2VuIHZhbHVlcyIsIGFkZGxhYmVscyA9IFRSVUUsIHlsaW0gPSBjKDAsIDUwKSkKCmZ2aXpfcGNhX2luZChyZXNfcGNhLCBsYWJlbD0ibm9uZSIsCiAgICAgICAgICAgICB0aXRsZT0iUENBIG9mIHJsb2cgZGF0YSIsCiAgICAgICAgICAgICBoYWJpbGxhZ2U9YXMuZmFjdG9yKG1ldGFfdGVtcCR0aW1lKSwKICAgICAgICAgICAgIG1lYW4ucG9pbnQ9RkFMU0UsCiAgICAgICAgICAgICBwb2ludHNoYXBlID0gMTkpIApgYGAKCk9uIHRoaXMgUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyB0aGUgY3ljbGljYWwgbmF0dXJlIG9mIHRoZSBleHBlcmltZW50IGlzIGFwcGFyZW50LiBGcm9tIHRoZSB0aW1lIHBvaW50IDBoLCB0aGUgdGltZSBwb2ludHMgZGVzY2VuZCBjb3VudGVyLWNsb2NrIHdpc2UsIHRvIHJldHVybiBhdCB0aGUgZmluYWwgMjRoIHRpbWUgcG9pbnQgYXQgdGhlIGxldmVsIG9mIHRoZSBmaXJzdCBvbmUuIE5vdGUgaG93IHRpbWUgcG9pbnRzIGF0IHRoZSBlbmQgb2YgdGhlIG5pZ2h0ICg2aCB0byAxMWgpIGFyZSBtb3JlIGNsb3NlbHkgcmVsYXRlZCB0aGVuIHRoZSBvdGhlcnMsIHRoaXMgaXMgYmVjYXVzZSBfQ2hsYW15ZG9tb25hc18gY2VsbHMgYXJlIHJlbGF0aXZlbHkgcXVpZXNjZW50IGF0IHRoaXMgcGFydCBvZiB0aGVpciBkYXkgY3ljbGUuCgojIyBIaWVyYXJjaGljYWwgY2x1c3RlcmluZyBvZiBzYW1wbGVzCgpgYGB7ciBoaWVyYXJjaGljYWxfY2x1c3RlcmluZywgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9Niwgb3V0LndpZHRoPSI5MCUiLCBmaWcuY2FwPSJIaWVyYXJjaGljYWwgY2x1c3RlcmluZyBvZiBybG9nIHRyYW5zZm9ybWVkIGNvdW50IGRhdGEuIn0KCmRpc3RzIDwtIGRpc3QodChhc3NheShybG9nX2RhdGEpKSkKcGFyKG1mcm93PWMoMSwxKSkKdHJlZV9ybG9nIDwtIGhjbHVzdChkaXN0cykKCm15X2NvbG9ycyA9IGMoIiNmZmM1NzYiLCAiIzQ0NWNkNyIsICIjZmZmMDRlIiwgIiMwMDE3ODkiLCAiI2ZhZjVjNiIpCgpwYXIoYmcgPSAiZGFya2dyZXkiLCBtZnJvdz1jKDEsIDEpKQpwbG90Q29sb3JlZENsdXN0ZXJzKHRyZWVfcmxvZywgbGFicyA9IG1ldGFfdGVtcCR0aW1lLAogICAgICAgICAgICAgICAgICAgIHlsYWIgPSBOQSwgeGxhYiA9IE5BLCBjZXggPSAsIGxhcyA9IDEsCiAgICAgICAgICAgICAgICAgICAgY29scyA9IG1ldGFfdGVtcCRjb2xvciwgY29sID0gIndoaXRlIiwKICAgICAgICAgICAgICAgICAgICBtYWluID0gIlNhbXBsZXMgRXVjbGlkaWFuIGRpc3RhbmNlIGhpZXJhcmNoaWNhbCAKY2x1c3RlcmluZywgcmxvZywgY29tcGxldGUgbGlua2FnZSIpCnJlY3QuaGNsdXN0KHRyZWVfcmxvZywgaz01LCBib3JkZXI9bXlfY29sb3JzKQpwYXIoYmc9IndoaXRlIikKCgojIFNhdmluZyBjbHVzdGVycwpjbHVzdGVyc19uYW1lcyA8LSBjKCJlYXJseV9uaWdodCIsCiAgICAgICAgICAgICAgICAgICAgIm5pZ2h0IiwKICAgICAgICAgICAgICAgICAgICAiZGF3biIsCiAgICAgICAgICAgICAgICAgICAgImRheSIsCiAgICAgICAgICAgICAgICAgICAgImR1c2siKQpjbHVzdGVyc19ybG9nIDwtIGN1dHJlZSh0cmVlX3Jsb2csIGs9NSkKbWV0YV90ZW1wJGNsdXN0ZXIgPC0gY2x1c3RlcnNfbmFtZXNbY2x1c3RlcnNfcmxvZ10KCmBgYAoKVGhlIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nIG9mIHRoZSB0cmFuc2Zvcm1lZCBkYXRhIGdpdmVzIGNvaGVyZW50IGNsdXN0ZXJzLCBncm91cGluZyBzYW1wbGVzIGFjY29yZGluZyB0byB0aW1lIHBlcmlvZHMuIEluIHRoaXMgcmVwb3J0IEkgZGVjaWRlZCB0byB1c2UgdGhlc2UgY2x1c3RlcnMgdG8gc2VwYXJhdGUgdGhlIHNhbXBsZXMgaW4gdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzLgoKCiMjIERpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIHdpdGggREVTZXEyCkhlcmUgSSB1c2UgdGhlIHByZXZpb3VzbHkgZGVmaW5lZCBjbHVzdGVycyBhcyBmb3JtdWxhIHRvIGxvb2sgZm9yIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyB3aXRoIERFU2VxMi4gSG93ZXZlciB0aGlzIGNhbiBhbHNvIGJlIGFjaGlldmVkIGJ5IHVzaW5nIGRpcmVjdGx5IHRoZSB0aW1lIGNvbmRpdGlvbnMgKGFzIHRoZSBSIHNjcmlwdCBpbiB0aGUgd29ya2Zsb3cgZG9lcykuIAoKYGBge3IgREVHLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIyMjIERFU2VxMiBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyBieSB0aW1lIHBvaW50ICMjIyMKZGRzVGltZXMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSBtYXRyaXhfY291bnRzX0RFU2VxMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IG1ldGFfdGVtcCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiBjbHVzdGVyKSAjIH4gdGltZV9mYWN0b3IgY291bGQgYmUgdXNlZCBpbnN0ZWFkCgojIyBFbGltaW5hdGlvbiBvZiBsb3dseSBleHByZXNzZWQgZ2VuZXMKCmRkc1RpbWVzIDwtIGRkc1RpbWVzWyByb3dTdW1zKGNvdW50cyhkZHNUaW1lcykpID4gNjAsIF0KCiMjIERpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzCmRkc1RpbWVzIDwtIERFU2VxKGRkc1RpbWVzKQp0aW1lX3BvaW50cyA8LSB1bmlxdWUobWV0YV90ZW1wJGNsdXN0ZXIpICMgdGltZV9mYWN0b3IgY291bGQgYmUgdXNlZCBpbnN0ZWFkCgp0aW1lX3JlcCA8LSBjKHJlcCh0aW1lX3BvaW50cywgYygxLCByZXAoMiwgbGVuZ3RoKHRpbWVfcG9pbnRzKS0xKSkpLCB0aW1lX3BvaW50c1sxXSkKcGFpcnMgPC0gbWF0cml4KGFzLmZhY3Rvcih0aW1lX3JlcCksIG5jb2wgPSAyLCBieXJvdyA9IFRSVUUpCgoKIyBTaWduaWZpY2FudCBnZW5lcyBpbml0aWFsaXNhdGlvbgpzaWduaWZpY2FudF9nZW5lcyA8LSBjKCkKCiMgRXh0cmFjdGlvbiBvZiBERVNlcTIgcmVzdWx0cwpmb3IgKGkgaW4gKDEgOiBucm93KHBhaXJzKSkpIHsKICAgIGVsZSA8LSBwYWlyc1tpLF0KICAgIHRleHQgPC0gcGFzdGUwKGVsZVsxXSwgIi8iLCBlbGVbMl0sICIgREVHOiIpCiAgICByZXNERVNlcSA8LSByZXN1bHRzKGRkc1RpbWVzLCBjb250cmFzdCA9IGMoImNsdXN0ZXIiLCBlbGVbMV0sIGVsZVsyXSksICMgInRpbWVfZmFjdG9yIiBjb3VsZCBiZSB1c2VkIGluc3RlYWQKICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXBlbmRlbnRGaWx0ZXJpbmcgPSBUUlVFLCBhbHBoYT0wLjAxKQogICAgbWVzc2FnZSh0ZXh0KQogICAgbWVzc2FnZSggc3VtKCByZXNERVNlcSRwYWRqIDwgMC4wMSwgbmEucm09VFJVRSApICkKICAgIHRlbXBfbGlzdCA8LSByb3cubmFtZXMocmVzREVTZXFbd2hpY2gocmVzREVTZXEkcGFkaiA8IDAuMDEpLF0pCiAgICBtZXNzYWdlKHBhc3RlMChjKGxlbmd0aCh0ZW1wX2xpc3QpL25yb3coY291bnRzX3J1bmRfZGYpICogMTAwKSwgIiAlIikpCiAgICBzaWduaWZpY2FudF9nZW5lcyA8LSB1bmlvbih0ZW1wX2xpc3QsIHNpZ25pZmljYW50X2dlbmVzKQp9CgpwcmludChwYXN0ZTAoIlRvdGFsIERFRyBpbiBhdCBsZWFzdCBvbmUgdGltZSB0cmFuc2l0aW9uOiAiLCAobGVuZ3RoKHNpZ25pZmljYW50X2dlbmVzKS9ucm93KGNvdW50c19ydW5kX2RmKSAqIDEwMCksICIgJSIpKQoKc2lnbl9kZiA8LSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHNpZ25pZmljYW50X2dlbmVzKQpzaWduX2RmJGRpZmZfZXhwciA8LSAieWVzIgpzaWduX2RmJGdlbmVfaWQgPC0gcm93Lm5hbWVzKHNpZ25fZGYpCgoKYGBgClRoZSB1c2Ugb2YgdGltZSBjb25kaXRpb24gKGFzIGluIHRoZSB3b3JrZmxvdyBSIHNjcmlwdCkgaW5zdGVhZCBvZiB0aGUgY2x1c3RlcnMgZ2l2ZXMgbGVzcyBERUcsIGFib3V0IDcwJS4KCiMjIFJoeXRobSBhbmFseXNpcyB3aXRoIERpc2NvUmh5dGhtCgoqKkRpc2NvUmh5dGhtOioqCgpNYXR0aGV3IENhcmx1Y2NpLCBBbGdpbWFudGFzIEtyacWhxI1pxatuYXMsIEhhb2hhbiBMaSwgUG92aWxhcyBHaWJhcywgS2Fyb2xpcyBLb25jZXZpxI1pdXMsIEFydCBQZXRyb25pcywgR2FicmllbCBPaCwgRGlzY29SaHl0aG06IGFuIGVhc3ktdG8tdXNlIHdlYiBhcHBsaWNhdGlvbiBhbmQgUiBwYWNrYWdlIGZvciBkaXNjb3ZlcmluZyByaHl0aG1pY2l0eSwgX0Jpb2luZm9ybWF0aWNzXywgVm9sdW1lIDM2LCBJc3N1ZSA2LCAxNSBNYXJjaCAyMDIwLCBQYWdlcyAxOTUy4oCTMTk1NCwgaHR0cHM6Ly9kb2kub3JnLzEwLjEwOTMvYmlvaW5mb3JtYXRpY3MvYnR6ODM0CgpgYGB7ciByaHl0aG1fYW5hbHlzaXNfRGlzY29SaHl0aG19CgojIENvbnZlcnRpbmcgcmxvZyBtYXRyaXggaW4gU0UgKFN1Ym1hcmlzZWQgRXhwZXJpbWVudCkpCmdlbmVfaWQgPC0gcm93Lm5hbWVzKGNvdW50c19ybG9nKQpybG9nX2RmIDwtIGFzLmRhdGEuZnJhbWUoY291bnRzX3Jsb2cpCnJsb2dfZGYgPC0gYWRkX2NvbHVtbihybG9nX2RmLCBnZW5lX2lkLCAuYmVmb3JlPTEpCmlucHV0X2RhdGEgPC0gZGlzY29ERnRvU0UocmxvZ19kZikKCmRpc2NvRGVzaWduU3VtbWFyeShpbnB1dF9kYXRhKQoKIyBPdXIgdGltZXBvaW50cyBhcmUgbm90IGVxdWlkaXN0YW50LCB3ZSBjYW4gdXNlIGVpdGhlciB0aGUgY29zaW5vciBvciBMb21iLVNjYXJnbGUgbWV0aG9kIHRvIGRldGVjdCBmZWF0dXJlIHJoeXRobXMKCiMgQ29zaW5vcgpyeXRobXNfZ2VuZXNfQ1MgPC0gZGlzY29PREFzKGlucHV0X2RhdGEsIHBlcmlvZCA9IDI0LCBtZXRob2QgPSAiQ1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpcmN1bGFyX3QgPSBUUlVFLCBuY29yZXMgPSA0KQoKIyBMb21iLVNjYXJnbGUKcnl0aG1zX2dlbmVzX0xTIDwtIGRpc2NvT0RBcyhpbnB1dF9kYXRhLCBwZXJpb2QgPSAyNCwgbWV0aG9kID0gIkxTIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lyY3VsYXJfdCA9IFRSVUUsIG5jb3JlcyA9IDQpCgoKcGFyKG1mcm93PWMoMSwyKSkKaGlzdChkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19DUykkQ1MucXZhbHVlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAicXZhbHVlIGNvc2lub3IiLAogICAgIHhsYWIgPSAicXZhbHVlIikKaGlzdChkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19MUykkTFMucXZhbHVlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAicXZhbHVlIExvbWItU2NhcmdsZSIsCiAgICAgeGxhYiA9ICJxdmFsdWUiKQpgYGAKClRoZSBMb21iLVNjYXJnbGUgcXZhbHVlIGRpc3RyaWJ1dGlvbiBoYXMgYSBwcm9ibGVtYXRpYyBwcm9maWxlLCB3ZSB3aWxsIGZvY3VzIG9uIENvc2lub3IuCgpgYGB7ciBjb3Npbm9yX3JoeXRobWljX2dlbmVzfQojIEV4dHJhY3RpbmcganVzdCB0aGUgZGF0YWZyYW1lcyBmcm9tIHRoZSBkaXNjb3J5dGhtIG91dHB1dApDU19kZiA8LSBkYXRhLmZyYW1lKHJ5dGhtc19nZW5lc19DUykKCgojIFJldHJlaXZpbmcgb25seSBtb3N0IHNpZ25pZmljYW50IGdlbmVzIAojIHF2YWx1ZSBpbmZlcmlvciB0byAwLjA1CkNTX2RmIDwtIENTX2RmW0NTX2RmJENTLnF2YWx1ZSA8IDAuMDUsXQoKCnBhcihtZnJvdz1jKDEsMikpCmhpc3QoQ1NfZGYkQ1MuYW1wbGl0dWRlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAiYW1wbGl0dWRlcyBjb3Npbm9yIAphZnRlciBzZWxlY3Rpb24iLAogICAgIHhsYWIgPSAiYW1wbGl0dWRlIikKCmhpc3QoQ1NfZGYkQ1MuYWNyb3BoYXNlLCBicmVha3MgPSAxMDAsIAogICAgIG1haW4gPSAiYWNyb3BoYXNlcyBjb3Npbm9yIAphZnRlciBzZWxlY3Rpb24iLAogICAgIHhsYWIgPSAiaG91ciIpCnBhcihtZnJvdz1jKDEsMSkpCgpgYGAKClRoZSBhY3JvcGhhc2UgaXMgdGhlIHRpbWUgd2hlbiB0aGUgZXhwcmVzc2lvbiBvZiB0aGUgZ2VuZSBwZWFrcy4gV2Ugd2lsbCBmb2N1cyBvbiB0aGUgYWNyb3BoYXNlIHBhcmFtZXRlciBpbnN0ZWFkIG9mIHRoZSBhbXBsaXR1ZGUgb2YgdGhlIGV4cHJlc3Npb24gc2lnbmFsIHRvIGZpbmQgcHV0YXRpdmUgcmVndWxhdG9ycy4gSW5kZWVkLCB3aGF0IHdlIGFyZSBpbnRlcmVzdGVkIGluIGlzIG5vdCB0aGUgaW50ZW5zaXR5IG9mIGdlbmUgZXhwcmVzc2lvbiwgYnV0IHJhdGhlciB0aGUgdGltaW5nIG9mIGV4cHJlc3Npb24uCgojIyBBbm5vdGF0aW9uCgpgYGB7ciBhbm5vdGF0aW9uX29mX2RhdGF9CgojIyBFeHRyYWN0aW9uIG9mIGFubm90YXRpb25zCnJvd19DUyA8LSByb3cubmFtZXMoQ1NfZGYpCgpDU19kZiRnZW5lX2lkIDwtIHJvd19DUwoKQ1NfZGYgPC0gbGVmdF9qb2luKENTX2RmLCBhbm5vdGF0aW9ucykKCmlkX29yZ2FuZWxsZSA9IGFubm90YXRpb25zX29yZ2FuZWxsZXMkZ2VuZV9pZApyb3cubmFtZXMoYW5ub3RhdGlvbnNfb3JnYW5lbGxlcykgPC0gaWRfb3JnYW5lbGxlCgpyb3dfQ1MgLT4gcm93Lm5hbWVzKENTX2RmKQoKCmZvciAoaWQgaW4gaWRfb3JnYW5lbGxlKSB7CiAgICBDU19kZltpZCwgImdlbmVfc3ltYm9sIl0gPC0gYW5ub3RhdGlvbnNfb3JnYW5lbGxlc1tpZCwiZ2VuZV9zeW1ib2wiXQp9CgoKQ1NfZGYkZ2VuZV9pZCA8LSByb3cubmFtZXMoQ1NfZGYpCgpDU19kZiRlbmNvZGVkIDwtICJOdWNsZXVzIgoKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2lkLCAiQ3JlTXQuIikpLCAiZW5jb2RlZCJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJlbmNvZGVkIl0gPC0gIkNobG9yb3BsYXN0IgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVNdC4iKSksICJzdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJzdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJDaGxvcm9wbGFzdCIKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2lkLCAiQ3JlTXQuIikpLCAic2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiJdIDwtICJNaXRvY2hvbmRyaW9uIgpDU19kZlt3aGljaChzdGFydHNXaXRoKENTX2RmJGdlbmVfaWQsICJDcmVDcC4iKSksICJzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uIl0gPC0gIkNobG9yb3BsYXN0IgoKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2Rlc2NyaXB0aW9uLCAiT2N0b3RyaWNvUGVwdGlkZSIpID09IFRSVUUpLCBdIC0+IENTX3N1YnNldF9vcHIKQ1NfZGZbd2hpY2goc3RhcnRzV2l0aChDU19kZiRnZW5lX2Rlc2NyaXB0aW9uLCAiUGVudGF0cmljb1BlcHRpZGUiKSA9PSBUUlVFKSwgXSAtPiBDU19zdWJzZXRfcHByCgoKIyBHZW5lcyBib3RoIHJoeXRobWljIGFuZCBERQpmaW5hbF9kYXRhIDwtIGxlZnRfam9pbihDU19kZiwgc2lnbl9kZiwgYnkgPSAiZ2VuZV9pZCIpCmZpbmFsX2RhdGEgPC0gZmluYWxfZGF0YVt3aGljaChmaW5hbF9kYXRhJGRpZmZfZXhwciA9PSAieWVzIiksXQpmaW5hbF9kYXRhIDwtIGZpbmFsX2RhdGFbIHdoaWNoKCFpcy5uYShmaW5hbF9kYXRhJENTLmFjcm9waGFzZSkpICwgXQoKYGBgCgojIyBHZW5lcmFsIHZpZXcgb2Ygcmh5dGhtaWMgZ2VuZXMgYWNyb3BoYXNlcwoKYGBge3IgZ2VuZXNfYWNyb3BoYXNlcywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NSwgb3V0LndpZHRoPSI5MCUiLCBmaWcuY2FwPSJBY3JvcGhhc2VzIGRpc3RyaWJ1dGlvbi4ifQpnZ3Bsb3QoZGF0YSA9IGZpbmFsX2RhdGEsIG1hcHBpbmcgPSBhZXMoeD1DUy5hY3JvcGhhc2UsIGZpbGw9ZW5jb2RlZCkpKwogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBDUy5hY3JvcGhhc2UsIHkgPSAuLmRlbnNpdHkuLiksIGJpbndpZHRoID0gMC41KSArCiAgICBmYWNldF93cmFwKH5lbmNvZGVkKSArCiAgICBsYWJzKCB4ID0gIkFjcm9waGFzZSIsIHkgPSAiR2VuZXMiLAogICAgICAgICAgdGl0bGUgPSJBY3JvcGhhc2VzIGRpc3RyaWJ1dGlvbiBhY2NvcmRpbmcgdG8gZW5jb2RpbmcgZ2Vub21lIiwKICAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOTllNTVjIiwgIiNlYjk1N2MiLCAiIzBmYzZlMSIpKQoKCgpjKHBhc3RlMCgiQ2hsb3JvcGxhc3QiLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJDaGxvcm9wbGFzdCIsXSksICIpIiksCiAgcGFzdGUwKCJDaHJvbW9zb21lIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hyb21vc29tZSIsXSksICIpIiksCiAgcGFzdGUwKCJDaWxpdW0iLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJDaWxpdW0iLF0pLCAiKSIpLAogIHBhc3RlMCgiQ3l0b3BsYXNtIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ3l0b3BsYXNtIixdKSwgIikiKSwKICBwYXN0ZTAoIkN5dG9za2VsZXRvbiIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIkN5dG9za2VsZXRvbiIsXSksICIpIiksCiAgcGFzdGUwKCJFbmRvcGxhc21pYyByZXRpY3VsdW0iLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJFbmRvcGxhc21pYyByZXRpY3VsdW0iLF0pLCAiKSIpLAogIHBhc3RlMCgiR29sZ2kgYXBwYXJhdHVzIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiR29sZ2kgYXBwYXJhdHVzIixdKSwgIikiKSwgICAKICBwYXN0ZTAoIk1lbWJyYW5lIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiTWVtYnJhbmUiLF0pLCAiKSIpLAogIHBhc3RlMCgiTWl0b2Nob25kcmlvbiIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIk1pdG9jaG9uZHJpb24iLF0pLCAiKSIpLAogIHBhc3RlMCgiTnVjbGV1cyIsICIgKCIsIG5yb3coZmluYWxfZGF0YVtmaW5hbF9kYXRhJHNpbXBsaWZpZWRfc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIk51Y2xldXMiLF0pLCAiKSIpLAogIHBhc3RlMCgiT3RoZXIiLCAiICgiLCBucm93KGZpbmFsX2RhdGFbZmluYWxfZGF0YSRzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJPdGhlciIsXSksICIpIiksCiAgcGFzdGUwKCJ1bmtub3duIiwgIiAoIiwgbnJvdyhmaW5hbF9kYXRhW2ZpbmFsX2RhdGEkc2ltcGxpZmllZF9zdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAidW5rbm93biIsXSksICIpIikpIC0+IGxvY2F0aW9ucwogICAKI2ZpbmFsX2RhdGEyIDwtIGZpbHRlcihmaW5hbF9kYXRhLCBzaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uICE9ICJ1bmtub3duIikKCmdncGxvdChkYXRhID0gZmluYWxfZGF0YSwgbWFwcGluZyA9IGFlcyh4PUNTLmFjcm9waGFzZSwgZmlsbD1zaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uKSkrCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0wLCB5bWF4ID0gSW5mLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0wLCB5bWF4ID0gSW5mLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTAsIHltYXggPSBJbmYsIGFscGhhID0wLjMpKwogICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBDUy5hY3JvcGhhc2UsIHkgPSAuLmRlbnNpdHkuLiksIGJpbndpZHRoID0gMC4zKSArCiAgICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgYWxwaGE9MC41KSArCiAgICBmYWNldF93cmFwKH5zaW1wbGlmaWVkX3N1YmNlbGx1bGFyX2xvY2F0aW9uKSsKICAgIGxhYnMoIHggPSAiQWNyb3BoYXNlIiwgeSA9ICJHZW5lcyIsCiAgICAgICAgICAgIHRpdGxlID0iQWNyb3BoYXNlcyBkaXN0cmlidXRpb24gYWNjb3JkaW5nIHRvIGNlbGx1bGFyIGxvY2F0aW9uIiwKICAgICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJDZWxsdWxhciBsb2NhdGlvbiIsIGxhYmVscyA9IGxvY2F0aW9ucykKCmBgYAoKIyMgUHV0YXRpdmUgYW5kIGtub3duIHJlZ3VsYXRvcnMKCmBgYHtyIE9UQUZ9CiMgUmVjb3ZlcmluZyBzb21lIHJoeXRobWljIE9UQUZzCm9wciA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9kZXNjcmlwdGlvbiwgIk9jdG90cmljb1BlcHRpZGUgUmVwZWF0IikpICwgXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCnBwciA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9kZXNjcmlwdGlvbiwgIlBlbnRhdHJpY29QZXB0aWRlIFJlcGVhdCIpKSAsIF0KdHByIDwtIGZpbmFsX2RhdGFbIHdoaWNoKHN0YXJ0c1dpdGgoZmluYWxfZGF0YSRnZW5lX2Rlc2NyaXB0aW9uLCAiVGV0cmF0cmljb1BlcHRpZGUgUmVwZWF0IikpICwgXQoKb3RhZiA8LSB1bmlvbl9hbGwob3ByLCBwcHIpCm90YWYgPC0gdW5pb25fYWxsKG90YWYsIHRwcikKCiMgQWRkaW5nIGV4cHJlc3Npb24gZGF0YToKY29sdW1ucyA8LSBjb2xuYW1lcyhvdGFmKQpvdGFmIDwtIGxlZnRfam9pbihvdGFmLCBybG9nX2RmKQpjb2xuYW1lcyhvdGFmKSA8LSBtYWtlLnVuaXF1ZShjKGNvbHVtbnMsIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpKSkKCiMgUHJlZGljdGVkIGNobG9yb3BsYXN0IGltcG9ydGVkIE9UQUZzCm11bHRpX290YWZfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiKSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG11bHRpX290YWZfY2hsb3JvIDwtIHJiaW5kKG11bHRpX290YWZfY2hsb3JvLCB0bXBfZGYpCn0KCm11bHRpX290YWZfY2hsb3JvIDwtIG11bHRpX290YWZfY2hsb3JvWy0xLF0KCiMgUHJlZGljdGVkIG1pdG9jaG9uZHJpb24gaW1wb3J0ZWQgT1RBRnMKbXVsdGlfb3RhZl9taXRvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiTWl0b2Nob25kcmlvbiIpLF0kZ2VuZV9zeW1ib2wpewogICAgb3RhZltvdGFmJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgbXVsdGlfb3RhZl9taXRvIDwtIHJiaW5kKG11bHRpX290YWZfbWl0bywgdG1wX2RmKQp9CgptdWx0aV9vdGFmX21pdG8gPC0gbXVsdGlfb3RhZl9taXRvWy0xLF0KCmBgYAoKYGBge3Igb3JnYW5lbGxlc19nZW5lc30KCiMgRXh0cmFjdGluZyBvcmdhbmVsbGFyIHJoeXRobWljIGdlbmVzCmNobG9ybyA8LSBmaW5hbF9kYXRhWyB3aGljaChzdGFydHNXaXRoKGZpbmFsX2RhdGEkZ2VuZV9pZCwgIkNyZUNwIikpICwgXQptaXRvIDwtIGZpbmFsX2RhdGFbIHdoaWNoKHN0YXJ0c1dpdGgoZmluYWxfZGF0YSRnZW5lX2lkLCAiQ3JlTXQiKSkgLCBdCgoKIyBBZGRpbmcgZXhwcmVzc2lvbiBkYXRhOgpjb2x1bW5zIDwtIGNvbG5hbWVzKGNobG9ybykKY2hsb3JvIDwtIGxlZnRfam9pbihjaGxvcm8sIHJsb2dfZGYpCmNvbG5hbWVzKGNobG9ybykgPC0gbWFrZS51bmlxdWUoYyhjb2x1bW5zLCByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKSkpCmNobG9ybyRnZW5lX3N5bWJvbCA8LSBtYWtlLnVuaXF1ZShjaGxvcm8kZ2VuZV9zeW1ib2wpCgpjb2x1bW5zIDwtIGNvbG5hbWVzKG1pdG8pCm1pdG8gPC0gbGVmdF9qb2luKG1pdG8sIHJsb2dfZGYpCmNvbG5hbWVzKG1pdG8pIDwtIG1ha2UudW5pcXVlKGMoY29sdW1ucywgcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykpKQoKCiMgQ2hsb3JvcGxhc3QKbXVsdGlfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIGNobG9ybyRnZW5lX3N5bWJvbCl7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgbXVsdGlfY2hsb3JvIDwtIHJiaW5kKG11bHRpX2NobG9ybywgdG1wX2RmKQp9CgptdWx0aV9jaGxvcm8gPC0gbXVsdGlfY2hsb3JvWy0xLF0KCgojIE1pdG9jaG9uZHJpb24KbXVsdGlfbWl0byA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBtaXRvJGdlbmVfc3ltYm9sKXsKICAgIG1pdG9bbWl0byRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG11bHRpX21pdG8gPC0gcmJpbmQobXVsdGlfbWl0bywgdG1wX2RmKQp9CgptdWx0aV9taXRvIDwtIG11bHRpX21pdG9bLTEsXQoKCmBgYAoKYGBge3IgZ2VuZV9leHByZXNzaW9uX21vZGVsX3Bsb3RzLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01LCBmaWcuY2FwPSJHZW5lIGV4cHJlc3Npb24gbW9kZWxzLiJ9CnBlcmlvZGU9MjQKCmdncGxvdChkYXRhID0gbXVsdGlfb3RhZl9jaGxvcm8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIGNobG9yb3BsYXN0IGxvY2FsaXNlZCBPVEFGcywgZXhwcmVzc2lvbiBtb2RlbHM6IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKCgpnZ3Bsb3QoZGF0YSA9IG11bHRpX2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGxldmVsID0gMC45NSwKICAgICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4gc2luKHggLyBwZXJpb2RlICogMiAqIHBpKSArIGNvcyh4IC8gcGVyaW9kZSAqIDIgKiBwaSksCiAgICAgICAgICAgICAgICBmdWxscmFuZ2UgPSBUUlVFKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBsYWJzKHkgPSAicmxvZyhjb3VudHMpIiwgeCA9ICJUaW1lIChoKSIsCiAgICAgICAgIHRpdGxlID0iUmh5dGhtaWMgY2hsb3JvcGxhc3QgZ2VuZXMsIGV4cHJlc3Npb24gbW9kZWxzOiIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgoKZ2dwbG90KGRhdGEgPSBtdWx0aV9vdGFmX21pdG8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIG1pdG9jaG9uZHJpb24gbG9jYWxpc2VkIE9UQUZzLCBleHByZXNzaW9uIG1vZGVsczoiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQoKCgpnZ3Bsb3QoZGF0YSA9IG11bHRpX21pdG8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IlJoeXRobWljIG1pdG9jaG9uZHJpb24gZ2VuZXMsIGV4cHJlc3Npb24gbW9kZWxzOiIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCgpgYGAKCgpUbyBwYWlyIE9UQUZzIGFuZCB0aGVpciBwdXRhdGl2ZSBvcmdhbmVsbGFyIG1STkEgdGFyZ2V0cyB3ZSBtdXN0IGxvb2sgYXQ6IAoKLSBPVEFGcyBhbmQgbVJOQSBsb2NhbGlzZWQgaW4gdGhlIHNhbWUgb3JnYW5lbGxlCgotIFdpdGggYWNyb3BoYXNlcyBvZmZzZXQgYnkgYSBmZXcgaG91cnMuIEZyb20gbVJOQSB0aGUgT1RBRiBtdXN0IGJlIHRyYW5zbGF0ZWQsIHRoZW4gaW1wb3J0ZWQgaW50byB0aGUgb3JnYW5lbGxlIHdoZXJlIGl0IG1pZ2h0IGFjdCBvbiBpdHMgbVJOQSB0YXJnZXQuIEhlcmUgSSB1c2VkIGEgNCBob3VycyBzaGlmdGVkIHBvdGVudGlhbCB3aW5kb3cuCgpgYGB7ciBPVEFGX21STkFfcGFpcnMsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTUsIGZpZy5jYXA9IkNhbmRpZGF0ZSBPVEFGL21STkEgdGFyZ2V0IHBhaXJzLiJ9CmFjcm9fbW9ybmluZ19jaGxvcm8gPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gY2hsb3JvW3doaWNoKGNobG9ybyRDUy5hY3JvcGhhc2UgPDE2ICYgY2hsb3JvJENTLmFjcm9waGFzZSA+MTIgKSxdJGdlbmVfc3ltYm9sKSB7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICAgICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgICAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICAgICAgYWNyb19tb3JuaW5nX2NobG9ybyA8LSByYmluZChhY3JvX21vcm5pbmdfY2hsb3JvLCB0bXBfZGYpCn0KCmFjcm9fbW9ybmluZ19jaGxvcm8gPC0gYWNyb19tb3JuaW5nX2NobG9yb1stMSxdCgoKb3RhZl9jaGxvcm9fYWNyb19kYXduIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiICYgb3RhZiRDUy5hY3JvcGhhc2UgPDEyICYgb3RhZiRDUy5hY3JvcGhhc2UgPjgpLF0kZ2VuZV9zeW1ib2wpewogICAgb3RhZltvdGFmJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgb3RhZl9jaGxvcm9fYWNyb19kYXduIDwtIHJiaW5kKG90YWZfY2hsb3JvX2Fjcm9fZGF3biwgdG1wX2RmKQp9CgpvdGFmX2NobG9yb19hY3JvX2Rhd24gPC0gb3RhZl9jaGxvcm9fYWNyb19kYXduWy0xLF0KCgojIFBsb3RzIAoKZ2dwbG90KGRhdGEgPSBvdGFmX2NobG9yb19hY3JvX2Rhd24sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID00LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSAxMywgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID00LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgeWxpbSg0LCAxMykgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZGF3biIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKCmdncGxvdChkYXRhID0gYWNyb19tb3JuaW5nX2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIHlsaW0oMTAsIDIxKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0xMCwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0xMCwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTEwLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBtUk5BLCBhY3JvcGhhc2UgaW4gdGhlIG1vcm5pbmciLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKYGBgCgpIZXJlLCB3ZSBjYW4gaWRlbnRpZnkga25vd24gT1RBRi9jaGxvcm9wbGFzdCBtUk5BIHBhaXJzL3RyaW9zOgoKLSBNREExLCBUREExIGFuZCBfYXRwQV8KCi0gTURIMSAoTVRISTEpLCBfYXRwSF8gYW5kIF9hdHBJXwoKLSBDQ1MyIGFuZCBfY2NzQV8KCi0gTUNHMSBhbmQgX3BldEdfCgoKQnV0IGFsc28gb3RoZXIgcG90ZW50aWFsIE9UQUYvbVJOQSBwYWlycyEKCgpgYGB7ciBPVEFGX21STkFfcGFpcnMyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01LCBmaWcuY2FwPSJDYW5kaWRhdGUgT1RBRi9tUk5BIHRhcmdldCBwYWlycy4ifQphY3JvX2FmdGVybm9vbl9jaGxvcm8gPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gY2hsb3JvW3doaWNoKGNobG9ybyRDUy5hY3JvcGhhc2UgPDIwICYgY2hsb3JvJENTLmFjcm9waGFzZSA+MTYgKSxdJGdlbmVfc3ltYm9sKSB7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICAgICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgICAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICAgICAgYWNyb19hZnRlcm5vb25fY2hsb3JvIDwtIHJiaW5kKGFjcm9fYWZ0ZXJub29uX2NobG9ybywgdG1wX2RmKQp9CgphY3JvX2FmdGVybm9vbl9jaGxvcm8gPC0gYWNyb19hZnRlcm5vb25fY2hsb3JvWy0xLF0KCgpvdGFmX2NobG9yb19hY3JvX2RheSA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBvdGFmW3doaWNoKG90YWYkc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIkNobG9yb3BsYXN0IiAmIG90YWYkQ1MuYWNyb3BoYXNlIDwxNiAmIG90YWYkQ1MuYWNyb3BoYXNlID4xMiksXSRnZW5lX3N5bWJvbCl7CiAgICBvdGFmW290YWYkZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgIHRtcF9kZiR0aW1lIDwtIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpCiAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICBvdGFmX2NobG9yb19hY3JvX2RheSA8LSByYmluZChvdGFmX2NobG9yb19hY3JvX2RheSwgdG1wX2RmKQp9CgpvdGFmX2NobG9yb19hY3JvX2RheSA8LSBvdGFmX2NobG9yb19hY3JvX2RheVstMSxdCgoKIyBQbG90cyAKCmdncGxvdChkYXRhID0gb3RhZl9jaGxvcm9fYWNyb19kYXksIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID00LCB5bWF4ID0gMTEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSAxMSwgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID00LCB5bWF4ID0gMTEsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgeWxpbSg0LCAxMSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZGF3biIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKCmdncGxvdChkYXRhID0gYWNyb19hZnRlcm5vb25fY2hsb3JvLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgeWxpbSgxMiwgMjEpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTEyLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTEyLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAyMywgeG1heCA9IEluZiwgeW1pbiA9MTIsIHltYXggPSAyMSwgYWxwaGEgPTAuMykrCiAgICBmYWNldF93cmFwKH5nZW5lKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IkNobG9yb3BsYXN0IG1STkEsIGFjcm9waGFzZSBhdCBkYXkiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKYGBgCgpIZXJlLCB3ZSBjYW4gaWRlbnRpZnkga25vd24gT1RBRi9jaGxvcm9wbGFzdCBtUk5BIHBhaXJzOgoKLSBNQUMxIGFuZCBfcHNhQ18KCi0gTUJCMSBhbmQgX3BzYkJfIAoKLSBNQkMxIGFuZCBfcHNiQ18KCi0gVEFBMSBhbmQgX3BzYUFfCgotIFRCQzIgYW5kIF9wc2JDXwoKLSBUQUIxIGFuZCBfcHNhQl8KCkFuZCBvdGhlciBwb3RlbnRpYWwgT1RBRi9tUk5BIHBhaXJzLi4uCgoKYGBge3IgT1RBRl9tUk5BX3BhaXJzMywgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmNhcD0iQ2FuZGlkYXRlIE9UQUYvbVJOQSB0YXJnZXQgcGFpcnMuIn0KYWNyb19ldmVuaW5nX2NobG9ybyA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBjaGxvcm9bd2hpY2goY2hsb3JvJENTLmFjcm9waGFzZSA8MjQgJiBjaGxvcm8kQ1MuYWNyb3BoYXNlID4yMCApLF0kZ2VuZV9zeW1ib2wpIHsKICAgIGNobG9yb1tjaGxvcm8kZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgICAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgICAgICBhY3JvX2V2ZW5pbmdfY2hsb3JvIDwtIHJiaW5kKGFjcm9fZXZlbmluZ19jaGxvcm8sIHRtcF9kZikKfQoKYWNyb19ldmVuaW5nX2NobG9ybyA8LSBhY3JvX2V2ZW5pbmdfY2hsb3JvWy0xLF0KCgpvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vbiA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBvdGFmW3doaWNoKG90YWYkc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIkNobG9yb3BsYXN0IiAmIG90YWYkQ1MuYWNyb3BoYXNlIDwyMCAmIG90YWYkQ1MuYWNyb3BoYXNlID4xNiksXSRnZW5lX3N5bWJvbCl7CiAgICBvdGFmW290YWYkZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgIHRtcF9kZiR0aW1lIDwtIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpCiAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICBvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vbiA8LSByYmluZChvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vbiwgdG1wX2RmKQp9CgpvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vbiA8LSBvdGFmX2NobG9yb19hY3JvX2FmdGVybm9vblstMSxdCgoKIyBQbG90cyAKCmdncGxvdChkYXRhID0gb3RhZl9jaGxvcm9fYWNyb19hZnRlcm5vb24sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID00LCB5bWF4ID0gMTEsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSAxMSwgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID00LCB5bWF4ID0gMTEsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgeWxpbSg0LCAxMSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZGF5IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgoKI2dncGxvdChkYXRhID0gYWNyb19ldmVuaW5nX2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKIyAgICB5bGltKDEyLCAyMSkgKwojICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTEyLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpICsKIyAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0xMiwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiMgICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID0xMiwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSsKIyAgICBmYWNldF93cmFwKH5nZW5lKSArCiMgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAojICAgICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4gc2luKHggLyBwZXJpb2RlICogMiAqIHBpKSArIGNvcyh4IC8gcGVyaW9kZSAqIDIgKiBwaSksCiMgICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwojICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwojICAgIGdlb21fcG9pbnQoKSArCiMgICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAojICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBtUk5BLCBhY3JvcGhhc2UgaW4gZXZlbmluZyIsCiMgICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwojICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKIyAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKcHJpbnQoIk5vIGNobG9yb3BsYXN0IGdlbmUgd2l0aCBtYXggZXhwcmVzc2lvbiBhdCBkdXNrLiIpCgpgYGAKCgoKCmBgYHtyIE9UQUZfbVJOQV9wYWlyczQsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTUsIGZpZy5jYXA9IkNhbmRpZGF0ZSBPVEFGL21STkEgdGFyZ2V0IHBhaXJzLiJ9CmFjcm9fbmlnaHRfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIGNobG9yb1t3aGljaChjaGxvcm8kQ1MuYWNyb3BoYXNlIDw0ICYgY2hsb3JvJENTLmFjcm9waGFzZSA+MCApLF0kZ2VuZV9zeW1ib2wpIHsKICAgIGNobG9yb1tjaGxvcm8kZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgICAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgICAgICBhY3JvX25pZ2h0X2NobG9ybyA8LSByYmluZChhY3JvX25pZ2h0X2NobG9ybywgdG1wX2RmKQp9CgphY3JvX25pZ2h0X2NobG9ybyA8LSBhY3JvX25pZ2h0X2NobG9yb1stMSxdCgoKb3RhZl9jaGxvcm9fYWNyb19kdXNrIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiICYgb3RhZiRDUy5hY3JvcGhhc2UgPDI0ICYgb3RhZiRDUy5hY3JvcGhhc2UgPjIwKSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG90YWZfY2hsb3JvX2Fjcm9fZHVzayA8LSByYmluZChvdGFmX2NobG9yb19hY3JvX2R1c2ssIHRtcF9kZikKfQoKb3RhZl9jaGxvcm9fYWNyb19kdXNrIDwtIG90YWZfY2hsb3JvX2Fjcm9fZHVza1stMSxdCgoKIyBQbG90cyAKCmdncGxvdChkYXRhID0gb3RhZl9jaGxvcm9fYWNyb19kdXNrLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9NCwgeW1heCA9IDgsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSA4LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTQsIHltYXggPSA4LCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIHlsaW0oNCwgOCkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZHVzayIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKCmdncGxvdChkYXRhID0gYWNyb19uaWdodF9jaGxvcm8sIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICB5bGltKDExLCAxNikgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9MTEsIHltYXggPSAxNiwgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImdvbGQiLCB4bWluID0gMTEsIHhtYXggPSAyMywgeW1pbiA9MTEsIHltYXggPSAxNiwgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID0xMSwgeW1heCA9IDE2LCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGxldmVsID0gMC45NSwKICAgICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4gc2luKHggLyBwZXJpb2RlICogMiAqIHBpKSArIGNvcyh4IC8gcGVyaW9kZSAqIDIgKiBwaSksCiAgICAgICAgICAgICAgICBmdWxscmFuZ2UgPSBUUlVFKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBsYWJzKHkgPSAicmxvZyhjb3VudHMpIiwgeCA9ICJUaW1lIChoKSIsCiAgICAgICAgIHRpdGxlID0iQ2hsb3JvcGxhc3QgbVJOQSwgYWNyb3BoYXNlIGluIGVhcmx5IG5pZ2h0IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKCmBgYAoKYGBge3IgT1RBRl9tUk5BX3BhaXJzNSwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmNhcD0iQ2FuZGlkYXRlIE9UQUYvbVJOQSB0YXJnZXQgcGFpcnMuIn0KYWNyb19uaWdodF9jaGxvcm8gPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gY2hsb3JvW3doaWNoKGNobG9ybyRDUy5hY3JvcGhhc2UgPDggJiBjaGxvcm8kQ1MuYWNyb3BoYXNlID40ICksXSRnZW5lX3N5bWJvbCkgewogICAgY2hsb3JvW2NobG9ybyRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgICAgIHRtcF9kZiR0aW1lIDwtIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpCiAgICAgICAgdG1wX2RmJGdlbmUgPC0gcHJvdAogICAgICAgIGFjcm9fbmlnaHRfY2hsb3JvIDwtIHJiaW5kKGFjcm9fbmlnaHRfY2hsb3JvLCB0bXBfZGYpCn0KCmFjcm9fbmlnaHRfY2hsb3JvIDwtIGFjcm9fbmlnaHRfY2hsb3JvWy0xLF0KCgpvdGFmX2NobG9yb19hY3JvX25pZ2h0IDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWZbd2hpY2gob3RhZiRzdWJjZWxsdWxhcl9sb2NhdGlvbiA9PSAiQ2hsb3JvcGxhc3QiICYgb3RhZiRDUy5hY3JvcGhhc2UgPDQgJiBvdGFmJENTLmFjcm9waGFzZSA+MCksXSRnZW5lX3N5bWJvbCl7CiAgICBvdGFmW290YWYkZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgIHRtcF9kZiR0aW1lIDwtIHJlcChjKDAsIDIsIDQsIDYsIDgsIDEwLCAxMC41LCAxMSwgMTEuNSwgMTIsIDE0LCAxNiwgMTgsIDIwLCAyMiwgMjQpLCBlYWNoPTMpCiAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICBvdGFmX2NobG9yb19hY3JvX25pZ2h0IDwtIHJiaW5kKG90YWZfY2hsb3JvX2Fjcm9fbmlnaHQsIHRtcF9kZikKfQoKb3RhZl9jaGxvcm9fYWNyb19uaWdodCA8LSBvdGFmX2NobG9yb19hY3JvX25pZ2h0Wy0xLF0KCgojIFBsb3RzIAoKZ2dwbG90KGRhdGEgPSBvdGFmX2NobG9yb19hY3JvX25pZ2h0LCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9NCwgeW1heCA9IDksIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSA5LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTQsIHltYXggPSA5LCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIHlsaW0oNCwgOSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgaW4gZWFybHkgbmlnaHQiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKCgpnZ3Bsb3QoZGF0YSA9IGFjcm9fbmlnaHRfY2hsb3JvLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgeWxpbSgxMiwgMTYpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTEyLCB5bWF4ID0gMTYsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTEyLCB5bWF4ID0gMTYsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAyMywgeG1heCA9IEluZiwgeW1pbiA9MTIsIHltYXggPSAxNiwgYWxwaGEgPTAuMykrCiAgICBmYWNldF93cmFwKH5nZW5lKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9IkNobG9yb3BsYXN0IG1STkEsIGFjcm9waGFzZSBhdCBuaWdodCIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgpgYGAKCmBgYHtyIE9UQUZfbVJOQV9wYWlyczYsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTUsIGZpZy5jYXA9IkNhbmRpZGF0ZSBPVEFGL21STkEgdGFyZ2V0IHBhaXJzLiJ9CmFjcm9fbmlnaHRfY2hsb3JvIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIGNobG9yb1t3aGljaChjaGxvcm8kQ1MuYWNyb3BoYXNlIDwxMiAmIGNobG9ybyRDUy5hY3JvcGhhc2UgPjggKSxdJGdlbmVfc3ltYm9sKSB7CiAgICBjaGxvcm9bY2hsb3JvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICAgICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgICAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICAgICAgYWNyb19uaWdodF9jaGxvcm8gPC0gcmJpbmQoYWNyb19uaWdodF9jaGxvcm8sIHRtcF9kZikKfQoKYWNyb19uaWdodF9jaGxvcm8gPC0gYWNyb19uaWdodF9jaGxvcm9bLTEsXQoKCm90YWZfY2hsb3JvX2Fjcm9fbmlnaHQgPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gb3RhZlt3aGljaChvdGFmJHN1YmNlbGx1bGFyX2xvY2F0aW9uID09ICJDaGxvcm9wbGFzdCIgJiBvdGFmJENTLmFjcm9waGFzZSA8OCAmIG90YWYkQ1MuYWNyb3BoYXNlID40KSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG90YWZfY2hsb3JvX2Fjcm9fbmlnaHQgPC0gcmJpbmQob3RhZl9jaGxvcm9fYWNyb19uaWdodCwgdG1wX2RmKQp9CgpvdGFmX2NobG9yb19hY3JvX25pZ2h0IDwtIG90YWZfY2hsb3JvX2Fjcm9fbmlnaHRbLTEsXQoKCiMgUGxvdHMgCgpnZ3Bsb3QoZGF0YSA9IG90YWZfY2hsb3JvX2Fjcm9fbmlnaHQsIG1hcHBpbmcgPSBhZXMoeD10aW1lLCB5PWdlbmVfZXhwcmVzc2lvbiwgZ3JvdXA9Z2VuZSwgY29sb3I9Z2VuZSkpICsgCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID00LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTQsIHltYXggPSAxMywgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDIzLCB4bWF4ID0gSW5mLCB5bWluID00LCB5bWF4ID0gMTMsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgeWxpbSg0LCAxMykgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBsb2NhdGVkIE9UQUZzLCBhY3JvcGhhc2UgYXQgZW5kIG9mIG5pZ2h0IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ29zaW5vciBtZXRob2QiKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgoKZ2dwbG90KGRhdGEgPSBhY3JvX25pZ2h0X2NobG9ybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIHlsaW0oMTIsIDIxKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0xMiwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0xMiwgeW1heCA9IDIxLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTEyLCB5bWF4ID0gMjEsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJDaGxvcm9wbGFzdCBtUk5BLCBhY3JvcGhhc2UgYXQgZGF3biIsCiAgICAgICAgIHN1YnRpdGxlID0gIkNvc2lub3IgbWV0aG9kIikrCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpKwogICAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgpgYGAKCkhlcmUsIHdlIGNhbiBpZGVudGlmeSBhIGtub3duIE9UQUYvY2hsb3JvcGxhc3QgbVJOQSBwYWlyOiBNUkwxIGFuZCBfcmJjTF8KCkFuZCBvdGhlciBwb3RlbnRpYWwgT1RBRi9tUk5BIHBhaXJzLi4uPwoKCmBgYHtyIE9UQUZfbVJOQV9wYWlyc19taXRvLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD04LCBmaWcuY2FwPSJDYW5kaWRhdGUgT1RBRi9tUk5BIHRhcmdldCBwYWlycy4ifQphY3JvX21pdG8gPC0gZGF0YS5mcmFtZSh0aW1lPTAsIGdlbmVfZXhwcmVzc2lvbj0wLjAsIGdlbmU9IiIpCgpmb3IgKHByb3QgaW4gbWl0byRnZW5lX3N5bWJvbCkgewogICAgbWl0b1ttaXRvJGdlbmVfc3ltYm9sID09IHByb3QsIDE5OjY2XSAlPiUKICAgICAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoMTo0OCksIG5hbWVzX3RvID0gInRpbWUiLCB2YWx1ZXNfdG8gPSAiZ2VuZV9leHByZXNzaW9uIikgLT4gdG1wX2RmCiAgICAgICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgICAgICB0bXBfZGYkZ2VuZSA8LSBwcm90CiAgICAgICAgYWNyb19taXRvIDwtIHJiaW5kKGFjcm9fbWl0bywgdG1wX2RmKQp9CgphY3JvX21pdG8gPC0gYWNyb19taXRvWy0xLF0KCgpvdGFmX21pdG9fYWNybyA8LSBkYXRhLmZyYW1lKHRpbWU9MCwgZ2VuZV9leHByZXNzaW9uPTAuMCwgZ2VuZT0iIikKCmZvciAocHJvdCBpbiBvdGFmW3doaWNoKG90YWYkc3ViY2VsbHVsYXJfbG9jYXRpb24gPT0gIk1pdG9jaG9uZHJpb24iKSxdJGdlbmVfc3ltYm9sKXsKICAgIG90YWZbb3RhZiRnZW5lX3N5bWJvbCA9PSBwcm90LCAxOTo2Nl0gJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDE6NDgpLCBuYW1lc190byA9ICJ0aW1lIiwgdmFsdWVzX3RvID0gImdlbmVfZXhwcmVzc2lvbiIpIC0+IHRtcF9kZgogICAgdG1wX2RmJHRpbWUgPC0gcmVwKGMoMCwgMiwgNCwgNiwgOCwgMTAsIDEwLjUsIDExLCAxMS41LCAxMiwgMTQsIDE2LCAxOCwgMjAsIDIyLCAyNCksIGVhY2g9MykKICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgIG90YWZfbWl0b19hY3JvIDwtIHJiaW5kKG90YWZfbWl0b19hY3JvLCB0bXBfZGYpCn0KCm90YWZfbWl0b19hY3JvIDwtIG90YWZfbWl0b19hY3JvWy0xLF0KCgojIFBsb3RzIAoKZ2dwbG90KGRhdGEgPSBvdGFmX21pdG9fYWNybywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJkYXJrZ3JheSIsIHhtaW4gPSAwLCB4bWF4ID0gMTEsIHltaW4gPTQsIHltYXggPSAxMywgYWxwaGEgPTAuMykgKwogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImdvbGQiLCB4bWluID0gMTEsIHhtYXggPSAyMywgeW1pbiA9NCwgeW1heCA9IDEzLCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTQsIHltYXggPSAxMywgYWxwaGEgPTAuMykrCiAgICBmYWNldF93cmFwKH5nZW5lKSArCiAgICB5bGltKDQsIDEzKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHNpbih4IC8gcGVyaW9kZSAqIDIgKiBwaSkgKyBjb3MoeCAvIHBlcmlvZGUgKiAyICogcGkpLAogICAgICAgICAgICAgICAgZnVsbHJhbmdlID0gVFJVRSkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgbGFicyh5ID0gInJsb2coY291bnRzKSIsIHggPSAiVGltZSAoaCkiLAogICAgICAgICB0aXRsZSA9Ik1pdG9jaG9uZHJpb24gbG9jYXRlZCBPVEFGcywiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKCgpnZ3Bsb3QoZGF0YSA9IGFjcm9fbWl0bywgbWFwcGluZyA9IGFlcyh4PXRpbWUsIHk9Z2VuZV9leHByZXNzaW9uLCBncm91cD1nZW5lLCBjb2xvcj1nZW5lKSkgKyAKICAgIHlsaW0oMTEsIDE2KSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMCwgeG1heCA9IDExLCB5bWluID0xMSwgeW1heCA9IDE2LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZ29sZCIsIHhtaW4gPSAxMSwgeG1heCA9IDIzLCB5bWluID0xMSwgeW1heCA9IDE2LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTExLCB5bWF4ID0gMTYsIGFscGhhID0wLjMpKwogICAgZmFjZXRfd3JhcCh+Z2VuZSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJNaXRvY2hvbmRyaW9uIG1STkEiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSsKICAgIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKYGBgCgoKYGBge3IgTkNMX2V4cHJlc3Npb24sIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTgsIGZpZy5jYXA9IlJoeXRobWljIE5DTCBtUk5BIGV4cHJlc3Npb24uIn0KbmNsX2RmIDwtIGRhdGEuZnJhbWUodGltZT0wLCBnZW5lX2V4cHJlc3Npb249MC4wLCBnZW5lPSIiKQoKZm9yIChwcm90IGluIG90YWYkZ2VuZV9zeW1ib2wpewogICAgaWYgKHN0YXJ0c1dpdGgocHJvdCwgIk5DTCIpIHwgc3RhcnRzV2l0aChwcm90LCAiTkNDIikgKXsKICAgICAgICBvdGFmW290YWYkZ2VuZV9zeW1ib2wgPT0gcHJvdCwgMTk6NjZdICU+JQogICAgICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygxOjQ4KSwgbmFtZXNfdG8gPSAidGltZSIsIHZhbHVlc190byA9ICJnZW5lX2V4cHJlc3Npb24iKSAtPiB0bXBfZGYKICAgICAgICB0bXBfZGYkdGltZSA8LSByZXAoYygwLCAyLCA0LCA2LCA4LCAxMCwgMTAuNSwgMTEsIDExLjUsIDEyLCAxNCwgMTYsIDE4LCAyMCwgMjIsIDI0KSwgZWFjaD0zKQogICAgICAgIHRtcF9kZiRnZW5lIDwtIHByb3QKICAgICAgICBuY2xfZGYgPC0gcmJpbmQobmNsX2RmLCB0bXBfZGYpCiAgICB9CiAgICAKfQoKbmNsX2RmIDwtIG5jbF9kZlstMSxdCgoKIyBQbG90cyAKCmdncGxvdChkYXRhID0gbmNsX2RmLCBtYXBwaW5nID0gYWVzKHg9dGltZSwgeT1nZW5lX2V4cHJlc3Npb24sIGdyb3VwPWdlbmUsIGNvbG9yPWdlbmUpKSArIAogICAgYW5ub3RhdGUoInJlY3QiLCBmaWxsID0gImRhcmtncmF5IiwgeG1pbiA9IDAsIHhtYXggPSAxMSwgeW1pbiA9MywgeW1heCA9IDksIGFscGhhID0wLjMpICsKICAgIGFubm90YXRlKCJyZWN0IiwgZmlsbCA9ICJnb2xkIiwgeG1pbiA9IDExLCB4bWF4ID0gMjMsIHltaW4gPTMsIHltYXggPSA5LCBhbHBoYSA9MC4zKSArCiAgICBhbm5vdGF0ZSgicmVjdCIsIGZpbGwgPSAiZGFya2dyYXkiLCB4bWluID0gMjMsIHhtYXggPSBJbmYsIHltaW4gPTMsIHltYXggPSA5LCBhbHBoYSA9MC4zKSsKICAgIGZhY2V0X3dyYXAofmdlbmUpICsKICAgIHlsaW0oMywgOSkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbGV2ZWwgPSAwLjk1LAogICAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiBzaW4oeCAvIHBlcmlvZGUgKiAyICogcGkpICsgY29zKHggLyBwZXJpb2RlICogMiAqIHBpKSwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFRSVUUpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeSA9ICJybG9nKGNvdW50cykiLCB4ID0gIlRpbWUgKGgpIiwKICAgICAgICAgdGl0bGUgPSJBbGwgcmh5dGhtaWMgTkNMIGV4cHJlc3Npb24iLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb3Npbm9yIG1ldGhvZCIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkrCiAgICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSkKYGBgCgoKCiMjIFJlZmVyZW5jZXMKCkViZXJoYXJkIFMsIExvaXNlbGF5IEMsIERyYXBpZXIgRCwgQnVqYWxkb24gUywgR2lyYXJkLUJhc2NvdSBKLCBLdXJhcyBSLCBDaG9xdWV0IFksIFdvbGxtYW4gRkEuIER1YWwgZnVuY3Rpb25zIG9mIHRoZSBudWNsZXVzLWVuY29kZWQgZmFjdG9yIFREQTEgaW4gdHJhcHBpbmcgYW5kIHRyYW5zbGF0aW9uIGFjdGl2YXRpb24gb2YgYXRwQSB0cmFuc2NyaXB0cyBpbiBfQ2hsYW15ZG9tb25hcyByZWluaGFyZHRpaV8gY2hsb3JvcGxhc3RzLiBfUGxhbnQgSi5fIDIwMTEgU2VwOzY3KDYpOjEwNTUtNjYuIGRvaTogMTAuMTExMS9qLjEzNjUtMzEzWC4yMDExLjA0NjU3LnguIEVwdWIgMjAxMSBKdWwgMTguIFBNSUQ6IDIxNjIzOTczLgoKV2FuZyBGLCBKb2huc29uIFgsIENhdmFpdW9sbyBNLCBCb2huZSBBViwgTmlja2Vsc2VuIEosIFZhbGxvbiBPLiBUd28gX0NobGFteWRvbW9uYXNfIE9QUiBwcm90ZWlucyBzdGFiaWxpemUgY2hsb3JvcGxhc3QgbVJOQXMgZW5jb2Rpbmcgc21hbGwgc3VidW5pdHMgb2YgcGhvdG9zeXN0ZW0gSUkgYW5kIGN5dG9jaHJvbWUgYjYgZi4gX1BsYW50IEouXyAyMDE1IEp1bjs4Mig1KTo4NjEtNzMuIGRvaTogMTAuMTExMS90cGouMTI4NTguIFBNSUQ6IDI1ODk4OTgyLgoKQ2xpbmUsIFMuIEcuLCBMYXVnaGJhdW0sIEkuIEEuIGFuZCBIYW1lbCwgUC4gUC4gKDIwMTcpIENDUzIsIGFuIE9jdGF0cmljb3BlcHRpZGUtUmVwZWF0IFByb3RlaW4sIElzIFJlcXVpcmVkIGZvciBQbGFzdGlkIEN5dG9jaHJvbWUgYyBBc3NlbWJseSBpbiB0aGUgR3JlZW4gQWxnYSBfQ2hsYW15ZG9tb25hcyByZWluaGFyZHRpaV8uIF9Gcm9udGllcnMgaW4gcGxhbnQgc2NpZW5jZV8sIDgsIDEzMDYuIGh0dHBzOi8vZG9pLm9yZy8xMC4zMzg5L2ZwbHMuMjAxNy4wMTMwNgoKVmlvbGEgUywgQ2F2YWl1b2xvIE0sIERyYXBpZXIgRCwgZXQgYWwuIE1EQTEsIGEgbnVjbGV1cy1lbmNvZGVkIGZhY3RvciBpbnZvbHZlZCBpbiB0aGUgc3RhYmlsaXphdGlvbiBhbmQgcHJvY2Vzc2luZyBvZiB0aGUgX2F0cEFfIHRyYW5zY3JpcHQgaW4gdGhlIGNobG9yb3BsYXN0IG9mIF9DaGxhbXlkb21vbmFzXy4gX1RoZSBQbGFudCBKb3VybmFsOiBmb3IgQ2VsbCBhbmQgTW9sZWN1bGFyIEJpb2xvZ3lfLiAyMDE5IEp1bjs5OCg2KToxMDMzLTEwNDcuIERPSTogMTAuMTExMS90cGouMTQzMDAuCgpTaGluLUljaGlybyBPemF3YSwgTWFyaW5hIENhdmFpdW9sbywgRG9taXRpbGxlIEphcnJpZ2UsIFJpY2hhcmQgS3VyYXMsIE1hcmsgUnV0Z2VycywgU3RlcGhhbiBFYmVyaGFyZCwgRG9taW5pcXVlIERyYXBpZXIsIEZyYW5jaXMtQW5kcsOpIFdvbGxtYW4sIFl2ZXMgQ2hvcXVldCwgVGhlIE9QUiBQcm90ZWluIE1USEkxIENvbnRyb2xzIHRoZSBFeHByZXNzaW9uIG9mIFR3byBEaWZmZXJlbnQgU3VidW5pdHMgb2YgQVRQIFN5bnRoYXNlIENGbyBpbiBfQ2hsYW15ZG9tb25hcyByZWluaGFyZHRpaV8sIF9UaGUgUGxhbnQgQ2VsbF8sIFZvbHVtZSAzMiwgSXNzdWUgNCwgQXByaWwgMjAyMCwgUGFnZXMgMTE3OeKAkzEyMDMsIGh0dHBzOi8vZG9pLm9yZy8xMC4xMTA1L3RwYy4xOS4wMDc3MAoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgo=